Java安全策略(Policy)

根據以前的幾篇文章我們知道,Java 2 平臺安全體系結構背后的基本原理可以總結如下:

一個系統級的安全策略定義了按以保護域(protection domains.)方式組織的執行代碼的訪問權限(按照應用程序的需要)。安全策略用于訪問控制檢查,這是由 JVM 在運行時執行的。

在 Java 2 平臺中,所有的代碼,不管它是本地代碼還是遠程代碼,都可以由策略來控制,此基礎上構建的 Java 2 平臺安全策略設計為根據 ProtectionDomain 授權訪問權限,而不是向單個的一段運行代碼授權這種權限。因此,每一個類或者對象“屬于”一個 ProtectionDomain ,安全策略對這個保護域授予了某種訪問權限。一個特定的 ProtectionDomain 封裝了一組類(例如,所有從特定位置上裝載、并用特定密鑰簽名的所有類),它們的實例將會授予同樣的一組權限。


保護域和代碼源

顯然,一定要能惟一地標識一段運行代碼以保證它的訪問權限沒有沖突。運行代碼的惟一標識屬性共有兩項:代碼的來源(代碼裝載到內存所用的 URL)和代碼的 signer 實體(由對應于運行代碼的數字簽名的一組公共密鑰指定)。這兩種特性的組合成運行代碼的 CodeSource 。現在可以提供 ProtectionDomain 的更嚴格定義了: ProtectionDomain 是一組 CodeSource 及其訪問權限。

Java 運行時通過名為 java.security.Policy 的類(的具體擴展)設置 ProtectionDomain 與授予它的權限之間的映射。這個類的默認擴展是 sun.security.provider.PolicyFile(參考jre下的java.security文件) 。它 從一個文件中獲得 CodeSource (由位置 URL 和 signer 標識別名)與授予它的權限之間的映射。可以通過環境變量 java.security.policy 將這個文件的位置作為輸入提供給 JVM。 Policy 類提供了一個名為 getPermissions() 的方法,可以調用它以獲得授予特定 CodeSource 的一組權限。

一個類與 其 ProtectionDomain 之間的映射是在類第一次裝載時由一個名為 SecureClassLoader 的特殊類裝載設置的。在 Java 2 平臺 SDK 1.4 中, ProtectionDomain 可以同時封裝(通過其構造函數傳遞的)靜態權限和動態權限,以前版本權限必須在構建時就已經知道。



運行時訪問檢查

由一個名為 SecurityManager 的類負責實施系統安全策略。在默認情況下不安裝安全管理器,必須通過一個在啟動時傳遞給 JVM 的、名為 java.security.manager 的環境變量顯式地指定。任何應用程序都可找到安裝的 SecurityManager 并調用它相應的 check<XXX> 方法。如果所要求的權限在給定運行時上下文中是授予的,那么調用將無聲地返回。如果權限沒有授予,那么將拋出一個 java.security.AccessControlException 。
Java 2 平臺安全體系結構通過引入一個名為 AccessController ,對 SecurityManager 類進行的所有 check<XXX> 方法調用都解釋為相應的 Permission 對象,并將它作為輸入參數傳遞給 AccessController 類的 checkPermission() 方法



訪問檢查方案

權限的算法是要計算所有權限的交集,確定權限集的交集的算法是在 AccessController 類的 checkPermission 方法中間接實現的,屬于能力更低的域的類不能通過調用屬于能力更高的域的類而變得更強大,而屬于能力更高的域中的類會在調用能力更低的類時損失其能力



Policy File Syntax

學習時參照"jre"lib"security"java.policy文件

一個Policy文件實質上是一個記錄列表,它可能含有一個“keystore”記錄,以及含有零個或多個“grant”記錄

其格式如下:
keystore "some_keystore_url", "keystore_type", "keystore_provider";
keystorePasswordURL "some_password_url";

“keystore”是一個私有密鑰(private keys)數據庫和相應的數字簽名,例如X.509證書。Policy文件中可能只有一條keystore記錄(也可能不含有該記錄),它可以出現在文件中grant記錄以外的任何地方。Policy配置文件中指定的keystores用于尋找grant記錄中指定的、簽名者的公共密鑰(public keys),如果任何grant記錄指定簽名者(signer_names),那么,keystore記錄必須出現在policy配置文件中。

 "some_keystore_url"是指keystore的URL位置,"keystore_type"是指keystore的類型。第二個選項是可選項,如果沒有指定,該類型則假定由安全屬性文件(java.security)中的"keystore.type"屬性來確定。keystore類型定義了keystore信息的存儲和數據格式,用于保護keystore中的私有密鑰和keystore完整性的算法。Sun Microsystems支持的缺省類型為“JKS”。

grant signedBy "signer_names", codeBase "URL",
        principal principal_class_name "principal_name",
        principal principal_class_name "principal_name",
         {

      permission permission_class_name "target_name", "action", 
          signedBy "signer_names";
      permission permission_class_name "target_name", "action", 
          signedBy "signer_names";
      
  };

在Policy文件中的每一個grant記錄含有一個CodeSource(一個指定的代碼)及其permission(許可)。

Policy文件中的每一條grant記錄遵循下面的格式,以保留字“grant”開頭,表示一條新的記錄的開始,“Permission”是另一個保留字,在記錄中用來標記一個新的許可的開始。每一個grant記錄授予一個指定的代碼(CodeBase)一套許可(Permissions)。

permission_class_name必須是一個合格并存在的類名,例如java.io.FilePermission,不能使用縮寫(例如,FilePermission)。

target_name用來指定目標類的位置,action用于指定目標類擁有的權限。
target_name可以直接指定類名(可以是絕對或相對路徑),目錄名,也可以是下面的通配符:
directory/* 目錄下的所有文件
*當前目錄的所有文件
directory/-目錄下的所有文件,包括子目錄
- 當前目錄下的所有文件,包括子目錄
《ALL FILES》文件系統中的所有文件
對于java.io.FilePermission,action可以是:read, write, delete和execute。
對于java.net.SocketPermission,action可以是:listen,accept,connect,read,write。

The exact meaning of a codeBase value depends on the characters at the end. A codeBase with a trailing "/"
 matches all class files (not JAR files) in the specified directory. A codeBase with a trailing "/*" matches
 all files (both class and JAR files) contained in that directory. A codeBase with a trailing "/-" matches
all files (both class and JAR files) in the directory and recursively all files in subdirectories contained
 in that directory. The following table illustrates the different cases.
/    表示所有的class文件(不包括Jar,不包括子目錄)
/*  
表示所有的class文件(包括Jar,不包括子目錄
/-   表示所有的class文件(包括Jar,包括子目錄


Policy文件中的屬性擴展(Property Expansion)

屬性擴展與shell中使用的變量擴展類似,它的格式為:
permission java.io.FilePermission
"${user.home}", "read";

具體詳細使用請參考:Policy官方文檔:Default Policy Implementation and Policy File Syntax


參考資源:
http://www.ibm.com/developerworks/cn/java/j-javaauth/
http://www.ibm.com/developerworks/cn/java/j-jaas/
http://java.sun.com/j2se/1.5.0/docs/guide/security/PolicyFiles.html#DefaultImpl
http://www.infosecurity.org.cn/article/websec/java/23218.html