Java Security Architecture--Java安全體系技術文檔翻譯(三)

返回目錄

3.2 java.security.CodeSource

本類擴展了HTML中的代碼庫(CodeBase)的概念,不僅囊括了代碼位置(URL)還包含了用於確認從該位置得到的簽名代碼的公鑰證書。注意到這不是一個HTML文件裏CodeBase標籤的等價物。每一個證書都由一個java.security.cert.Certificate表示,每一個URL都由一個java.net.URL表示。

3.3 java.security.Policy

一個Java應用環境的系統安全規則指定了對於不同來源的代碼應該賦予哪些許可,由一個Policy對象代表。更確切的說,它是由一個實現了Policy抽象方法的子類來代表。
爲了讓一個applet(或者一個運行在SecurityManager之下的應用)被允許執行一些安全動作,例如讀或寫一個文件,這個applet(或應用)必須被賦予該動作的許可。唯一的例外是代碼總是自動擁有其所在目錄及其子目錄的文件的讀許可;它不需要明確的許可就有權限讀這些文件。
可以存在很多的Policy對象,雖然在任何時刻都只能有一個“起作用”。當前註冊的Policy對象可以通過getPolicy方法來得到,也可以通過setPolicy方法來修改當前註冊的Policy(需要由擁有重置Policy權限的代碼來執行)。
Policy對象中的規則信息的來源取決於Policy的具體實現。例如規則配置可能被存儲爲一個ASCII文件,一個序列化的Policy類的二進制文件,或者一個數據庫。有一個Policy實現可以通過靜態的policy配置文件來獲得規則信息。

3.3.1 規則文件的格式

在Policy實現中,規則可以描述在一個或者多個規則配置文件中。規則配置文件指出對於某特定來源的代碼應該賦予哪些許可。配置文件必須使用UTF-8編碼。
一個規則配置文件包括一個入口記錄(entry)的列表。它可以包含一個“keystore”的入口記錄,並且包含0個或多個“grant”入口記錄。
一個keystore是一個包含私鑰及其對應的用來鑑定公鑰的數字證書(例如X.509證書鏈)的數據庫。keytool實用工具用來創建並管理keystores。在規則配置文件中指定的keystore用來尋找在該文件的“grant”入口記錄中指定的簽名者的公鑰。如果任何一個grant入口記錄指定了簽名者別稱,或者任何一個grant入口記錄指定了一個當事人身份(principal)別稱(參照下面),那麼一個keystore入口記錄必須出現在規則配置文件中。
同時,在規則文件中只能有一個keystore入口記錄(第一個之後的其他keystore會被忽略),並且可以出現在規則文件中grant入口記錄之外的任何地方。它遵循如下的語法:
keystore "some_keystore_url", "keystore_type";
這裏,"some_keystore_url"指定了keystore的URL位置,"keystore_type"指定了keystore的類型。後者是可選的。如果沒有指定,就認爲keystore類型是由安全屬性文檔中的屬性“keystore.type”指定。
URL是一個基於規則文件位置的相對路徑。這樣如果安全屬性文檔中指定規則文件的位置如下:

policy.url.1=http://foo.bar.com/blah/some.policy

該規則文件有一個入口:
keystore ".keystore";

那麼keystore將會從下面地址被加載:
http://foo.bar.com/blah/.keystore

URL也可以是絕對路徑。
keystore類型定義了keystore信息的存儲和數據格式,以及用來保護保存在該keystore中的私鑰和keystore自身的完整性的算法。Sun微系統默認支持的類型是一個名爲“JKS”的專有keystore。
規則文檔中的每一個“grant”入口記錄都由一個代碼源(CodeSource)和它的一組許可組成。實際上,一個代碼源由一個URL以及一組證書所組成,相應的規則文件一條入口記錄中包含了一個URL以及一組簽名者的名稱。系統在諮詢keystore並證實這些簽名者的證書後創建相應的代碼源。
規則文件中的每一個grant入口記錄都擁有下面的格式,開頭的“grant”是一個保留字,標誌着一個新入口記錄的開始,括號內的是可選項。在每一個入口記錄內,開頭的“permission”是另一個保留字,標誌着該入口記錄內開始定義一個新許可。每一個grant入口記錄賦予一個特定的代碼源(CodeSource)及若干當事人身份(principals)以一組許可。

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 ...
};

逗號前後允許有空格。許可類型的名字必須是全類名,如java.io.FilePermission,不能被簡化(如FilePermission)。
注意到動作(action)字段是可選的,所以如果許可類不需要它的話可以被省略。如果提供動作,那它必須緊跟着目標(target)字段。
代碼庫URL值的確切意思取決於其最後一個字符。一個以“/”結尾的代碼庫匹配該路徑下的所有類文件(不包括JAR文件)。一個以“/*”結尾的代碼庫匹配該路徑下的所有文件(既包括類文件又包括JAR文件)。一個以“/-”結尾的代碼庫配備該路徑及其所有遞歸子路徑下的所有文件(既包括類文件又包括JAR文件)。
代碼庫字段(URL)是可選的,如果省略,則代表“所有代碼庫”。
第一次出現的簽名者字段是一個字符串別名,該別名通過一個分離的機制導航到一組與該簽名者相關的公鑰(其證書在keystore裏)上。這些公鑰用來證實某一簽名類確實是被這些簽名者所簽名的。
該簽名者字段可以是一個逗號分隔的包含多個簽名者名稱的字符串,例如“Adam,Eve,Charles”,意味着被Adam和Eve和Charlest同時簽名(就是說,關係是AND不是OR)。
該字段是可選的,如果省略,意味着“任何簽名者”,或者換句話說,壓根不關心該代碼是否被簽名。
第二次出現的簽名者字段,在一個Permission入口記錄內,代表了對該Permission類字節碼簽名的私鑰所對應的公鑰保存在keystore中的別名。該許可入口只有在證實了對應的Permission實現類的字節碼被別名所代表的簽名者正確簽名以後纔會生效(也就是,會基於本條入口記錄授予訪問控制許可)。
當事人身份(principal)值由一個 類名/身份名 鍵值對所描述,該鍵值對必須存在於當前執行線程的當事人身份集合中。當事人身份集合通過當事人(Subject)對象與正在執行的代碼相關聯。當事人身份字段是可選的,如果忽略就代表“任何當事人身份”。
KeyStore別名替換的注意事項:
如果當事人身份的 類名/身份名 鍵值對使用一個引號擴起來的字符串來表示,它會被當作一個keystore別名來處理。通過別名來諮詢和查找keystore,從而得到一個X509的證書。如果找到了,那麼該當事人身份會自動被作爲一個javax.security.auth.x500.X500Principal類型來對待,並且身份名會自動被當作從證書中得到的主題辨識名(subject distinguished name)對待。如果X509證書沒有找到,整個grant入口記錄會被忽略掉。
CodeBase,SignedBy,和Principal相互之間的次序是不重要的。
一種規則文件格式的非正式的BNF語法如下所示,其中非大寫的短語是最終短語,也就是真正規則中的短語。

PolicyFile -> PolicyEntry | PolicyEntry; PolicyFile
PolicyEntry -> grant {PermissionEntry}; |
           grant SignerEntry {PermissionEntry} |
           grant CodebaseEntry {PermissionEntry} |
           grant PrincipalEntry {PermissionEntry} |
           grant SignerEntry, CodebaseEntry {PermissionEntry} |
           grant CodebaseEntry, SignerEntry {PermissionEntry} |
           grant SignerEntry, PrincipalEntry {PermissionEntry} |
           grant PrincipalEntry, SignerEntry {PermissionEntry} |
           grant CodebaseEntry, PrincipalEntry {PermissionEntry} |
           grant PrincipalEntry, CodebaseEntry {PermissionEntry} |
           grant SignerEntry, CodebaseEntry, PrincipalEntry {PermissionEntry} |
           grant CodebaseEntry, SignerEntry, PrincipalEntry {PermissionEntry} |
           grant SignerEntry, PrincipalEntry, CodebaseEntry {PermissionEntry} |
           grant CodebaseEntry, PrincipalEntry, SignerEntry {PermissionEntry} |
           grant PrincipalEntry, CodebaseEntry, SignerEntry {PermissionEntry} |
           grant PrincipalEntry, SignerEntry, CodebaseEntry {PermissionEntry} |
           keystore "url"
SignerEntry -> signedby (a comma-separated list of strings)
CodebaseEntry -> codebase (a string representation of a URL)
PrincipalEntry -> OnePrincipal | OnePrincipal, PrincipalEntry
OnePrincipal -> principal [ principal_class_name ] "principal_name" (a principal)
PermissionEntry -> OnePermission | OnePermission PermissionEntry
OnePermission -> permission permission_class_name
                 [ "target_name" ] [, "action_list"]
                 [, SignerEntry];

現在我們給一些例子。下面的規則給予Roland簽名的代碼以a.b.Foo的許可:
grant signedBy "Roland" {
    permission a.b.Foo;
}

下面的規則給予所有的代碼一個FilePermission(不管是什麼簽名者或者代碼基)
grant {
    permission java.io.FilePermission ".tmp", "read";
};

下面的規則給予由Li和Roland同時簽名的代碼以兩條許可:
grant signedBy "Roland,Li" {
  permission java.io.FilePermission "/tmp/*", "read";
  permission java.util.PropertyPermission "user.*";
};

下面的規則給予Li簽名的並且來自源http://java.sun.com的代碼以兩條許可:
grant codeBase "http://java.sun.com/*", signedBy "Li" {
    permission java.io.FilePermission "/tmp/*", "read";
    permission java.io.SocketPermission "*", "connect";
};

下面的規則對於同時被Li和Roland簽名的代碼,並且僅當com.abc.TVPermission的字節碼是被Li簽名的時候,給予他們兩條權限:
grant signedBy "Roland,Li" {
  permission java.io.FilePermission "/tmp/*", "read";
  permission com.abc.TVPermission "channel-5", "watch", 
      signedBy "Li";
};

包含第二個簽名者字段的原因是當一個許可類尚未在當前Java運行時環境中註冊時防止欺騙發生。例如,一份com.abc.TVPermission類的拷貝可以作爲一個遠程JAR存檔的一部分被下載,並且用戶安全規則中可能包含了一個關於它的入口記錄。由於存檔不是長期存活的,於是當第二次com.abc.TVPermission類被下載的時候,可能是從另一個不同的網站,因此確保第二份拷貝是真的就變得至關重要了,既然在用戶的安全規則中存在該許可的入口,這很可能反映出了用戶對於第一份類字節碼拷貝是很信任的。
我們選擇使用數字簽名的方式來確保真實性,而不是保存第一份拷貝並用它來跟第二分拷貝進行比較的原因是,該許可類的作者可能由於新的設計或代碼實現,已經正當的更新了類文件。
請注意:文件路徑字符串必須使用平臺相關的格式;在統一文件描述語言出現之前這是有必要的。上面的例子展示了在Solaris系統上合適的字符串格式。在Windows系統上,當你直接使用字符串指定一個文件路徑時,你需要雙反斜槓來代表一個實際上的單反斜槓,例如

grant signedBy "Roland" {
  permission java.io.FilePermission "C:\\users\\Cathy\\*", "read";
};

這是因爲字符串會被一個java.io.StreamTokenizer標記器處理,該標記器使用“\”作爲一個轉義符(例如:“\n”代表換行)因此要求兩個反斜槓來表示一個反斜槓。在標記器處理完上述FilePermission的目標字符串,將雙反斜槓轉換爲單反斜槓以後,實際路徑的最終結果是
"C:\users\Cathy\*"

最後,這裏是一些當事人身份(principal)相關的grant入口記錄:
grant principal javax.security.auth.x500.X500Principal "cn=Alice" {
  permission java.io.FilePermission "/home/Alice", "read, write";
};

該規則允許任何以X500Principal, "cn=Alice"身份執行的代碼擁有對於“/home/Alice”的讀和寫的許可。
接下來的例子展示了一個同時包含了代碼源和當事人身份信息的grant入口記錄。

grant codebase "http://www.games.com",
        signedBy "Duke",
        principal javax.security.auth.x500.X500Principal "cn=Alice" {
    permission java.io.FilePermission "/tmp/games", "read, write";
  };

該規則允許從“www.games.com”下載的,被“Duke”簽名的,並被“cn=Alice”身份執行的代碼,擁有對於“/tmp/games”目錄的讀和寫許可。
下面的例子展示了一個包含keystore別名替換的grant語句:

keystore "http://foo.bar.com/blah/.keystore";

  grant principal "alice" {
    permission java.io.FilePermission "/tmp/games", "read, write";
  };

“alice”會被替換成javax.security.auth.x500.X500Principal "cn=Alice",假設keystore中與別名“alice”相關的X.509證書有一個主題辨識名“cn=Alice”。該規則允許以X500Principal "cn=Alice"身份執行的代碼擁有對“/tmp/games”目錄讀和寫的許可。

3.3.2 規則文件中的屬性展開

規則文件(policy files)和安全屬性文件(security properties file)是支持屬性展開(property expansion)的。
屬性展開類似於shell腳本中的變量展開。就是說,當一個像下面一樣的字符串

"${some.property}"

出現在規則文件或安全屬性文件中時,它會被展開成某特定的系統屬性值。例如,
permission java.io.FilePermission "${user.home}", "read";

會將"${user.home}"展開成"user.home"所對應的系統屬性的值。如果該變量的值是"/home/cathy",那麼上面這句話等同於
permission java.io.FilePermission "/home/cathy", "read";

你可以使用特殊記號"${/}"來輔助實現平臺無關的規則文件,該符號是"${file.separator}"的一個縮寫。這樣就可以允許像如下規則
permission java.io.FilePermission "${user.home}${/}*", "read";

如果user.home是/home/cathy,並且你是在Solaris系統上,則上面的語句會變成:
permission java.io.FilePermission "/home/cathy/*", "read";

如果user.home是C:\users\cathy並且你在一個Windows系統上,則上面的語句會變成:
permission java.io.FilePermission "C:\users\cathy\*", "read";

另外,作爲一個特殊情況,如果你在一個代碼庫中展開一個屬性,例如
grant codeBase "file:/${java.home}/lib/ext/"

那麼任何文件分隔符將會被自動轉換成/,因爲代碼庫是URL格式所以此處需要/。這樣一來,在Windows系統上,就算java.home的值是C:\j2sdk1.2,上面的語句也會轉換成
grant codeBase "file:/C:/j2sdk1.2/lib/ext/"

這樣的話在代碼庫中你就不需要也不應該使用 ${/}。
規則文件中任何雙引號字符串允許的地方都可以使用屬性擴展。包括signedby, codebase, target名稱, 和action字段。
安全屬性文件中的屬性"policy.expandProperties"控制着是否允許屬性展開。如果該屬性值爲true(默認值),則允許屬性展開。
請注意,你不能使用嵌套屬性;他們不會起作用的。例如,

"${user.${foo}}"

不會起作用,即使將user的屬性“foo”賦了值“home”也沒用。因爲屬性解析器無法識別嵌套屬性;它簡單的查找第一個"${",然後就開始查找第一個"}"並嘗試將得到的"${user.$foo}"解釋爲一個屬性,由於系統中沒有這個屬性,所以會失敗。
同樣注意:如果在一個grant入口記錄,permission入口記錄,或者keystore入口記錄中無法展開一個屬性,則該入口記錄會被忽略。例如,如果系統沒有定義“foo”這個屬性,但是你配置了:

grant codeBase "${foo}" {
  permission ...;
  permission ...;
};

這樣一來,這個grant入口記錄中的所有許可都會被忽略。如果你配置了
grant {
  permission Foo "${foo}";
  permission Bar;
};

則僅僅permission Foo "${foo}";這個入口記錄會被忽略。最後,如果你配置了
keystore "${foo}";

那麼keystore入口記錄會被忽略。
最後注意:在Windows系統上,當你直接用字符串指定一個文件路徑時,你需要用兩個反斜槓來代表一個反斜槓,例如

"C:\\users\\cathy\\foo.bat"

這是因爲字符串會被一個java.io.StreamTokenizer標記器處理,該標記器使用“\”作爲一個轉義符(例如:“\n”代表換行)因此要求兩個反斜槓來表示一個反斜槓。在標記器處理完上述字符串,將雙反斜槓轉換爲單反斜槓以後,實際路徑的最終結果是
"C:\users\cathy\foo.bat"

一個字符串中的屬性展開會發生在標記器處理完該字符串之後。這樣如果你有下面的字符串
"${user.home}\\foo.bat"

首先會由標記器來處理這個字符串,將雙反斜槓轉換成單反斜槓,結果是
"${user.home}\foo.bat"

然後,屬性${user.home}會被展開,最終結果是
"C:\users\cathy\foo.bat"

假如user.home的值是"C:\users\cathy"。當然,爲了平臺獨立考慮,字符串在一開始不指定具體的斜槓是一種更好的方式,那就是,使用屬性${/}來代替,例如
"${user.home}${/}foo.bat"

3.3.3 規則文件中的一般展開

規則文件也支持一般格式的展開。例如,許可名稱可能包含一個如下格式的字符串:
${{protocol:protocol_data}}

如果在一個許可名稱中出現了這樣一個字符串,則protocol的值決定了要發生的展開的具體類型,protocol_data是用來輔助執行本次展開的。protocol_data可能是空的,在這種情況下上面的字符串應該簡單的使用如下格式:
${{protocol}}

默認的規則文件的實現支持兩種類型的protocol
1. ${{self}}
self這種協議指定了要使用一個或多個當事人身份的class/name鍵值對替換${{self}}這個字符串。具體的替換內容取決於該許可所屬的grant語句的內容。
如果grant語句不包括任何當事人的信息,那麼該許可會被忽略(那些在目標名(target)中包含了${{self}}的許可,只在基於當事人身份上下文的grant語句中才會生效)。例如,在下面的grant語句中BarPermission總是會被忽略:

grant codebase "www.foo.com", signedby "duke" {
    permission BarPermission "... ${{self}} ...";
};

如果grant語句中包含了當事人身份信息,${{self}}會被替換成當事人身份的信息。例如在下面的grant語句中,BarPermission中的${{self}}會被替換成javax.security.auth.x500.X500Principal "cn=Duke":

grant principal javax.security.auth.x500.X500Principal "cn=Duke" {
     permission BarPermission "... ${{self}} ...";
};


如果在grant語句中包含了一個逗號隔開的當事人身份列表,那麼${{self}}也會被替換成逗號隔開的當事人身份列表。在當事人類和身份名都使用通配符的情況下,${{self}}會被替換成在當前安全控制上下文快照(AccessControlContext)中的當事人(Subject)所關聯的所有身份(Principals)。(也就是通配符計算完成後的當事人身份列表)
下面例子描述了一個同時涉及到self協議和keystore別稱替換的場景:

keystore "http://foo.bar.com/blah/.keystore";

grant principal "duke" {
    permission BarPermission "... ${{self}} ...";
};

在上面例子中,“duke”會首先被展開爲
javax.security.auth.x500.X500Principal "cn=Duke"

假設keystore中別名“duke”所關聯的X.509證書有一個主題辨別名"cn=Duke"。然後,${{self}}會被擴展後的當事人身份替換爲:javax.security.auth.x500.X500Principal "cn=Duke"。


2. ${{alias:alias_name}}
alias協議指示了一個java.security.KeyStore別名替換。使用的keystore就是在keystore入口記錄中定義的那個。alias_name代表了一個保存在keystore之中的別名。
${{alias:alias_name}}會被替換成javax.security.auth.x500.X500Principal "DN",當DN代表了alias_name所包含的證書的主題辨別名時。例如:

keystore "http://foo.bar.com/blah/.keystore";

grant codebase "www.foo.com" {
      permission BarPermission "... ${{alias:duke}} ...";
};

在上面例子中別名爲“duke”的X.509證書從foo.bar.com/blah/.keystore這個keystore中獲得。假設duke的證書指定"o=dukeOrg, cn=duke"爲其主題辨別名,那麼${{alias:duke}}會被替換成javax.security.auth.x500.X500Principal "o=dukeOrg, cn=duke"。
如有如下的錯誤發生則permission的入口記錄會被忽略:
keystore入口沒指定
alias_name沒有提供
alias_name代表的證書沒有獲得到
獲得的證書不是一個X.509證書

3.3.4 許可的授予

當以某個當事人身份執行一個來自於某代碼源的類,安全機制會諮詢規則(policy)對象來決定授予其什麼樣的許可。這是通過調用註冊到VM的Policy對象的getPermissions或者implies方法來完成的。
明顯的,一個安全域中的給定的代碼源可以匹配規則中多個入口記錄裏的代碼源,例如當允許使用通配符“*”的時候。

下面的算法用來在規則中定位合適的許可集合。


  1. 如果代碼被簽名過,則匹配公鑰。
  2. 如果一個公鑰無法被規則(規則中定義的keystore)驗證,則忽略該公鑰。如果所有的公鑰都被忽略,則認爲該代碼沒有被簽名。
  3. 如果匹配上了公鑰,或者沒有指定簽名者{嘗試在規則中爲這些公鑰匹配所有的URL}
  4. 如果匹配上了公鑰(或者沒有指定簽名者),並且也找到了匹配的URL(或者沒有指定代碼庫codebase){試着將規則中所有的當事人與當前執行線程中的當事人進行匹配}
  5. 如果key,URL,或者當事人中有任一項不匹配,使用內置的默認許可,也就是初始的沙盒許可。


一個規則入口的代碼庫URL值的確切含義取決於其最後的字符。一個以"/"結尾的代碼庫匹配指定目錄下的所有類文件(不包括JAR文件)。一個以"/*"結尾的代碼庫匹配指定目錄下的所有文件(既包括類文件也包括JAR文件)。一個以"/-"結尾的代碼庫包括指定目錄及其遞歸子目錄下的所有文件(既包括類文件也包括JAR文件)。

舉例來說,如果規則中給出"http://java.sun.com/-",那麼該網站上的所有代碼庫都能匹配到這個規則入口。包括"http://java.sun.com/j2se/sdk/"和"http://java.sun.com/people/gong/appl.jar"。
如果多個入口被匹配到,那麼這些入口中的所有的許可都會被授予。換句話說,許可授予是可疊加的。例如,如果由A簽名的代碼可得到許可X,而由B簽名的代碼可得到許可Y,並且沒有指定代碼庫,那麼同時被A和B簽名的代碼可以得到許可X和許可Y。同樣的,如果代碼庫爲"http://java.sun.com/-"的代碼可得到許可X,而代碼庫爲"http://java.sun.com/people/*"的代碼可得到許可Y,並且沒有指定簽名者,那麼一個從"http://java.sun.com/people/applet.jar"而來的applet就會同時得到許可X和Y。
注意這裏對URL的匹配是純粹語法上的。例如,一個規則可以給出一個指定URL爲"ftp://ftp.sun.com"的入口記錄。這樣的入口記錄只有在一個能直接使用ftp獲得要執行的代碼的時候纔是有用的。
文件URL可以被用來指定來自本地文件系統的地址。例如,要指定Solaris系統上的/home/cathy/temp目錄下的所有文件,你可以使用

"file:/home/cathy/temp/*"

要指定Windows系統上的C盤的"temp"文件夾下的所有問題,你可以使用
"file:/c:/temp/*"

注意:代碼基URL總是使用斜槓(而非反斜槓),不用管他們用在哪個平臺上。
你也可以使用一個絕對路徑名,例如

"/home/gong/bin/MyWonderfulJava"

3.3.5 默認的系統和用戶規則文件

在Policy實現中,規則可以在一個或多個規則配置文件中指定。配置文件指定來自某代碼源的代碼被授予哪些許可。
一個規則文件可以通過一個簡單的文檔編輯器來編輯,或者通過一個後面將講到的圖形化規則工具來編輯。
默認存在一個系統範圍的規則文件,和一個用戶規則文件。
系統規則文件默認存放在

{java.home}/lib/security/java.policy  (Solaris)
{java.home}\lib\security\java.policy  (Windows)

這裏,java.home是一個系統屬性,該屬性指定Java 2 SDK安裝在哪個目錄下。
用戶規則文件默認存放在

{user.home}/.java.policy  (Solaris)
{user.home}\.java.policy  (Windows)

這裏,user.home是一個系統屬性,該屬性指定用戶的home目錄。
當Policy初始化時,系統規則先被加載,然後再將用戶規則添加上去。如果兩個規則都不存在,一個內置規則會被使用。內置規則與最初的沙盒規則一樣。
規則文件的位置在安全屬性文件(security properties file)中指定,安全屬性文件的位置是

{java.home}/lib/security/java.security  (Solaris)
{java.home}\lib/security\java.security  (Windows)

規則文件的位置在具有如下格式的屬性值中指定
policy.url.n

這裏,n是一個數字。你在每行中以如下格式指定一個這樣的屬性:
policy.url.n=URL

這裏,URL是一個URL的描述。例如,在安全屬性文件中如下所示定義默認的系統和用戶規則
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy

實際上你可以指定很多的URL,包括“http://”格式的,所有指定的規則文件都會被加載。你也可以註釋或修改第二條配置以不執行讀取默認用戶規則文件。
加載的算法是從policy.url.1開始,保持增加數字直到沒有找到對應的URL。因此,如果你配置了policy.url.1和policy.url.3,那麼policy.url.3不會被讀取。
你也可以在應用執行的時候指定一個額外的或者不同的規則文件。這可以通過命令行參數"-Djava.security.policy"來實現,該命令行參數設置java.security.policy屬性。例如,如果你使用

java -Djava.security.manager -Djava.security.policy=pURL SomeApp

這裏,pURL是一個指定規則文件位置的URL,然後這個規則文件就會被加載並添加到在安全屬性文件中配置的那些規則文件之後。(參數"-Djava.security.manager"確保默認的安全管理器被註冊,這樣的話應用就受規則檢查的支配,正如在“Applet和應用的安全管理”那一節所描述的。並不要求SomeApp內部註冊一個安全管理器。)
如果你使用下面的命令行,其中用了雙等號,那麼只有該命令行中指定的規則文件會被使用;所有其他規則文件都會被忽略。

java -Djava.security.manager -Djava.security.policy==pURL SomeApp

如果你希望給一個appletviewer傳遞一個規則文件,同樣可以使用一個"-Djava.security.policy"參數,如下所示:
appletviewer -J-Djava.security.policy=pURL  myApplet

注意:假如安全屬性文件中屬性"policy.allowSystemProperty"的值設置爲false(默認是true),那麼命令行中的"-Djava.security.policy"將會被忽略(java和appletviewer的命令行都是)。

3.3.6 定製規則計算

當前對於Policy類的設計並沒有像它本應該達到的那樣適用。我們給予了這個問題很多的思考並在小心謹慎的改進,並在一定程度上確保我們定義的方法對於絕大部分常見的情形都是適用的。同時,也可以提供一個替代規則類來替換掉默認的規則類,只要前者是一個Policy抽象類的子類,並實現了getPermissions方法(如果有必要的話也可重新實現其他方法)。
Policy實現類可以通過重設"policy.provider"(在安全屬性文件中定義)的值來改變,將其設置爲想要的Policy實現類的全限定名。安全屬性文件的位置是

{java.home}/lib/security/java.security (Solaris)
{java.home}\lib\security\java.security (Windows)

這裏,{java.home}代表了運行環境安裝的目錄--要麼是Java 2 SDK中jre的目錄,要麼是Java 2運行時環境的根目錄。
屬性policy.provider指定了規則類的名字,默認如下:

policy.provider=sun.security.provider.PolicyFile

想定製的話,你可以改變該屬性的值來指定另外一個類,如
policy.provider=com.mycom.MyPolicy

注意MyPolicy必須是java.security.Policy的一個子類。或許應該強調一下這種重寫規則類的方式只是一種暫時的解決方案,而一個更廣泛適用的規則接口將會使這種重寫變得沒必要。

3.4 java.security.GeneralSecurityException

這是一個繼承自java.lang.Exception的新的異常類。提出該異常類的意圖是,與安全及安全包相關的異常應該有兩種類型。
java.lang.SecurityException和它的子類應該是一個運行時異常(無需檢查,不用聲明),這些異常很可能導致程序執行的終止。
這種異常都是在某些類型的安全衝突被發現以後拋出。例如,當一些代碼企圖訪問一個文件,但是它沒有訪問許可時,會拋出這種異常。應用開發者如果想的話,可以捕捉這些異常。
java.security.GeneralSecurityException是一個java.lang.Exception(必須被聲明或捕捉)的子類,在安全包中發生的所有其他類型的異常都會拋出該異常。
這種異常是與安全相關的但是並不致命。例如,傳入一個無效的密鑰很可能並不是一個安全衝突,因此應該被開發者捕捉並處理。

此刻在java.security包中仍然有兩個異常繼承自RuntimeException。在目前階段爲了向後兼容我們沒法修改它們。我們將在未來再返回到這個問題。






===========================================================================

本技術文檔的翻譯工作由不動明王1984獨自完成,特此聲明。

翻譯辛苦,珍惜勞動,引用時請註明出處!

===========================================================================






返回目錄


上一篇:Java Security Architecture--Java安全體系技術文檔翻譯(二)

下一篇:Java Security Architecture--Java安全體系技術文檔翻譯(四)


發佈了17 篇原創文章 · 獲贊 35 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章