java安全-安全管理器
基本概念
安全管理器是一個負責控制具體操作是否允許執行的類,它主要負責檢查的操作包括如下內容:
- 建立一個新的類載入器;
- 退出虛擬機器
- 使用反射訪問另一個類的成員
- 訪問本地檔案
- 開啟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