基本概念
安全管理器是一個負責控制具體操作是否允許執行的類,它主要負責檢查的操作包括如下內容:
- 創建一個新的類加載器;
- 退出虛擬機
- 使用反射訪問另一個類的成員
- 訪問本地文件
- 打開socket連接
- 啟動打印作業
- 訪問系統剪貼板
- 打開一個頂層窗口
java.lang.SecurityManager類包含了很多checkXXXX方法,SecurityManager 中其他所有 check 方法的默認實現都是調用 SecurityManager checkPermission 方法來確定調用線程是否具有執行所請求操作的權限。
權限分為以下類別:文件、套接字、網絡、安全性、運行時、屬性、AWT、反射和可序列化。管理各種權限類別的類是 java.io.FilePermission、java.net.SocketPermission、java.net.NetPermission、java.security.SecurityPermission、java.lang.RuntimePermission、java.util.PropertyPermission、java.awt.AWTPermission、java.lang.reflect.ReflectPermission 和 java.io.SerializablePermission。
除前兩個(FilePermission 和 SocketPermission)類以外的所有類都是 java.security.BasicPermission 的子類,而 java.security.BasicPermission 類又是頂級權限類 java.security.Permission 的抽象子類。
安全策略文件:
類裝載器用Policy對象幫助它們決定,把一段代碼導入虛擬機時應該給它們什么樣的權限. 任何時候,每一個應用程序都只有一個Policy對象.
Sun的java1.2平台具體的Policy子類采用在一ASCII策略文件中用上下文無關文法描述安全策略.
一個策略文件包括了一系列grant子句,每一個grant子句將一些權限授給一個代碼來源。
grant codesource
{
permission1;
permission2;
}
保護域(ProtectionDomain)
當類裝載器將類型裝入java虛擬機時,它們將為每一個類型指派一個保護域,保護域定義了授予 一段特定的代碼的所有權限.裝載入java虛擬機的每一個類型都屬於一個且僅屬於一個保護域.
訪問控制器(AccessController)
-
mplies() 判斷一個Permissioin對象的權限,是否隱含(imply)在另一個Permissioin對象的權限中。
-
checkPermission() AccessController的核心方法,這個方法決定一個特定的操作能否被允許. 它自頂向下檢查棧,只要它遇到一個沒有權限楨,它將拋出一個AccessControlException導常。
-
doPrivileged()有的時候,調用棧較上層(更靠近棧頂)的代碼可能希望執行一段代碼,而這段代碼在調用棧的較下層是不允許執行的。為了使可信的代碼執行較不可靠的代碼操作(這段不可靠的代碼位於調用棧的較下層且沒有執行這個操作的權限),AccessController類重載了四個名為doPrivileged()的靜態方法.
1:AccessController會忽略調用doPrivileged()方法的調用者的調用者的權限.
2:Permission: 權限是用抽象類java.security.Permission的一個子類的實例表示的.
3:CodeSource: 代碼來源,包含代碼庫URL和簽名者.
4: Permissions: PermissionCollection(權限集合)的子類實例:判斷用戶是否可以讀取文件
import java.io.*;
class UserSecurityManager extends SecurityManager {
private String passWord;
private String userName;
UserSecurityManager(String passWord,String userName) {
super();
this.passWord=passWord;
this.userName=userName;
}
private boolean accessOK() {
System.out.println("請輸入用戶名和密碼,用逗號隔開");
BufferedReader dis = new BufferedReader(new InputStreamReader(System.in));
try {
String[] value=dis.readLine().split(",");
if (value[0].equals(userName)&&value[1].equals(passWord))
return true;
else
return false;
} catch (IOException e) {
return false;
}
}
public void checkRead(FileDescriptor filedescriptor) {
if (!accessOK())
throw new SecurityException("您沒有讀文件權限");
}
public void checkRead(String filename) {
if (!accessOK())
throw new SecurityException("您沒有讀文件權限");
}
public void checkRead(String filename, Object executionContext) {
if (!accessOK())
throw new SecurityException("您沒有讀文件權限");
}
public void checkWrite(FileDescriptor filedescriptor) {
if (!accessOK())
throw new SecurityException("您沒有寫文件權限!");
}
public void checkWrite(String filename) {
if (!accessOK())
throw new SecurityException("您沒有寫文件權限!");
}
}
import java.io.*;
public class TestSecurity
{
public static void main(String args[])
{
try {
System.setSecurityManager(new UserSecurityManager("123456","wang"));
} catch (SecurityException se) {
System.out.println("安全管理器啟動,您需要輸入用戶名和密碼才能繼續操作");
}
try {
BufferedReader fis = new BufferedReader(new FileReader("input.txt"));
String inputString;
while ((inputString = fis.readLine()) != null) {
System.out.println(inputString);
}
fis.close();
} catch (IOException ioe) {
System.out.println("I/O 讀取文件失敗"+" "+ioe.getMessage());
}catch(Exception e)
{
System.out.println(e.toString());
}
}
}
運行結果:
輸入不匹配用戶名和密碼:
請輸入用戶名和密碼,用逗號隔開
zhang,1234
java.lang.SecurityException: 您沒有讀文件權限
輸入正確的用戶名和密碼,成功讀取文件信息。
請輸入用戶名和密碼,用逗號隔開
wang,123456
hello word
