Java 誕生於網絡時代,安全是核心設計目標。其安全模型經歷三次重大演進:
| 版本 | 模型特徵 | 關鍵機制 |
|---|---|---|
| JDK 1.0 | 沙箱模型 | 本地代碼全信任,遠程代碼嚴格限制在 JVM 沙箱內,無法訪問本地資源。 |
| JDK 1.1 | 安全策略 + 代碼簽名 | 引入策略文件,用戶可授予遠程代碼特定權限;簽名代碼可獲更多信任。 |
| JDK 1.2+ | 保護域 + 權限集合 | 所有代碼(本地/遠程)由類加載器分配到不同保護域,每域擁有權限集合;引入 doPrivileged 臨時提權。 |
| 現代 | 域模型 | 虛擬機劃分系統域(核心資源)與應用域(業務代碼),應用域通過系統域代理訪問資源,實現細粒度隔離。 |

當調用鏈上某方法調用 AccessController.checkPermission(perm) 時,ACC 按以下邏輯決定是否授權:
AccessControlException。doPrivileged(特權動作)。doPrivileged 實現。doPrivileged → 調用無權限 X。問題:新線程不自動繼承父線程安全上下文,導致子線程權限檢查忽略父線程限制,可能造成安全漏洞。
解決:創建線程時保留父線程 AccessControlContext,或使用 AccessController.getContext() 獲取快照傳遞給子線程,子線程調用 acc.checkPermission(perm) 即在父上下文中檢查。
// 父線程捕獲上下文快照
AccessControlContext acc = AccessController.getContext();
// 傳遞給子線程,子線程執行:
acc.checkPermission(permission); // 等價於在父線程上下文中檢查
FileUtil,路徑 D:\workspace\projectX\bin,擁有該目錄寫權限。MyPolicy.txt 僅授予 ProjectX bin 目錄寫權限。public class FileUtil {
private static final String FOLDER_PATH = "D:\\workspace\\projectX\\bin";
// 普通方式:受調用者權限約束
public static void makeFile(String fileName) {
try { new File(FOLDER_PATH + "\\" + fileName).createNewFile(); }
catch (AccessControlException | IOException e) { e.printStackTrace(); }
}
// 特權方式:臨時提權至 FileUtil 所在域權限
public static void doPrivilegedAction(final String fileName) {
AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() { makeFile(fileName); return null; }
});
}
}
public class DemoDoPrivilege {
public static void main(String[] args) {
System.setSecurityManager(new SecurityManager()); // 開啟安全檢查
// 1. 特權調用 → 成功
FileUtil.doPrivilegedAction("temp1.txt");
// 2. 直接 new File → 失敗(DemoDoPrivilege 無權限)
new File("D:\\workspace\\projectX\\bin\\temp2.txt").createNewFile();
// 3. 普通調用 FileUtil.makeFile → 失敗(調用鏈含無權限 DemoDoPrivilege)
FileUtil.makeFile("temp3.txt");
}
}
java -Djava.security.policy=.\\MyPolicy.txt -classpath D:\workspace\projectY\bin;D:\workspace\projectX\bin demo.security.DemoDoPrivilege
Create temp1.txt via privileged action ... SUCCESS
Create temp2.txt via File ... AccessControlException: Access denied (write)
Create temp3.txt via FileUtil ... AccessControlException: Access denied (write)
doPrivileged 突破。AccessControlContext,確保權限邊界不因線程切換而失效。Java 安全模型通過保護域、權限集合與特權動作,構建了靈活且嚴格的訪問控制體系。深入理解 AccessController 檢查算法與上下文傳遞機制,是編寫安全健壯系統級代碼的關鍵。