Policy文件中的屬性擴(kuò)展(Property Expansion)
---- 屬性擴(kuò)展與shell中使用的變量擴(kuò)展類似,它的格式為:
"${some.property}"
實(shí)際使用的例子為:
permission java.io.FilePermission
"${user.home}", "read";
"${user.home}"的值為"d:\Project",
因此,下面的語句和上面的語句是一樣的:
permission java.io.FilePermission "
d:\Project ", "read";
三. 實(shí)例
---- 當(dāng)初始化Policy時(shí),首先裝載系統(tǒng)Policy,然后再增加用戶Policy,如果兩者都不存在,則使用缺省的Policy,即原始的沙箱模型。
---- 系統(tǒng)Policy文件的缺省位置為:
{java.home}/lib/security/java.policy (Solaris)
{java.home}\lib\security\java.policy (Windows)
用戶Policy文件的缺省位置為:
{user.home}/.java.policy (Solaris)
{user.home}\.java.policy (Windows)
---- 其實(shí),在實(shí)際使用中,我們可能不會(huì)象上面介紹的那么復(fù)雜,特別是在不使用數(shù)字簽名時(shí)。這時(shí),我們完全可以借鑒JDK 1.2提供給我們的現(xiàn)成的\jdk1.2\jre\lib\security\java.policy文件,根據(jù)我們的需要作相應(yīng)的修改,本文就針對(duì)不使用數(shù)字簽名情況詳細(xì)說明安全策略文件的用法。
---- 下面,是一個(gè)完整的在Windows 95/98/NT下使用的.java.policy文件。在文件中,分別使用注釋的形式說明了每個(gè)“permission”記錄的用途。
// For LanServerTalk.java and LanClientTalk.java
grant {
//對(duì)系統(tǒng)和用戶目錄“讀”的權(quán)限
permission java.util.PropertyPermission
"user.dir", "read";
permission java.util.PropertyPermission
"user.home", "read";
permission java.util.PropertyPermission
"java.home", "read";
permission java.util.PropertyPermission
"java.class.path", "read";
permission java.util.PropertyPermission
"user.name", "read";
//對(duì)線程和線程組的操作權(quán)限
permission java.lang.RuntimePermission
"modifyThread";
permission java.lang.RuntimePermission
"modifyThreadGroup";
//操作Socket端口的各種權(quán)限
permission java.net.SocketPermission
"-", "listen";
permission java.net.SocketPermission
"-", "accept";
permission java.net.SocketPermission
"-", "connect";
permission java.net.SocketPermission "-", "read";
permission java.net.SocketPermission "-", "write";
//讀寫文件的權(quán)限
permission java.io.FilePermission "-", "read";
permission java.io.FilePermission "-", "write";
//退出系統(tǒng)的權(quán)限,例如System.exit(0)
permission java.lang.RuntimePermission "exitVM";
};
四. java.policy文件的使用
---- 對(duì)于windows 95/98/NT,使用.java.policy文件的方法主要有下面兩種。
---- 1. 使用缺省目錄
---- 我們可以簡單地將編輯好的.java.policy文件拷貝到windows 95/98/NT的HOME目錄,這時(shí),所有的applet(或Java應(yīng)用程序)可能都擁有某些相同的權(quán)限,使用起來簡單,但不靈活(例如:對(duì)于java.io.FilePermission ,其目標(biāo)類的target_name必須使用絕對(duì)路徑),如果不是在企業(yè)內(nèi)部網(wǎng)中使用,還可能存在一定安全隱患。
---- 2. 在命令行中指定
---- 在命令行,如果我們希望傳遞一個(gè)Policy文件給appletviewer,還可以使用"-J-Djava.security.policy"參數(shù)來指定policy的位置:
appletviewer -J-Djava.security.
policy=pURL myApplet
---- pURL為Policy文件的位置。下面,是一個(gè)實(shí)際的例子,以當(dāng)前目錄的.java.policy文件所指定的安全策略運(yùn)行當(dāng)前目錄的LanServerTalk.html(文件中裝載并運(yùn)行LanServerTalk.java):
appletviewer -J-Djava.security.policy
=.java.policy LanServerTalk.html
---- 這種方法使用靈活,特別是作為一個(gè)軟件包在企業(yè)內(nèi)部網(wǎng)中發(fā)布時(shí),安裝、設(shè)置和遷移軟件,基本無須修改Policy文件的內(nèi)容,使用起來相當(dāng)簡單,而且,安全許可的范圍控制較精細(xì)。
__________________________________________________________________________________
缺省策略實(shí)現(xiàn)和策略文件語法
上次修改時(shí)間: 1998 年 10 月 30 日
Java 應(yīng)用程序環(huán)境的策略(對(duì)不同來源的代碼指定權(quán)限)由 Policy 對(duì)象來表示。更明確地說,就是由 Policy
類(包含在 java.security
包中)的實(shí)現(xiàn)抽象方法的 Policy
子類來表示。
Policy 對(duì)象所用策略信息的源位置由 Policy 實(shí)現(xiàn)決定。缺省 Policy 實(shí)現(xiàn)從靜態(tài)策略配置文件獲得自己的信息。本文檔的其余部分?jǐn)⑹隽巳笔?Policy 實(shí)現(xiàn)及其所讀取的策略文件中必須使用的語法。有關(guān)使用 Policy Tool 來創(chuàng)建策略文件(不必知道所需語法)的詳細(xì)信息,請(qǐng)參閱《策略工具文檔》 (for Solaris) (for Windows)。
以下是本文檔其余部分的概要:
- 缺省 Policy 實(shí)現(xiàn)
- 缺省策略文件位置
- 更改 Policy 實(shí)現(xiàn)
- 策略文件語法
- 策略文件示例
- 策略文件中的屬性擴(kuò)展
- 相關(guān)文檔
在缺省 Policy 實(shí)現(xiàn)中,可在一個(gè)或多個(gè)策略配置文件中指定策略。配置文件的作用是指定特定代碼源的代碼所能獲得的權(quán)限。
可利用簡單的文本編輯器或 Policy Tool 實(shí)用程序來編寫策略文件。
缺省情況下,系統(tǒng)上只有單個(gè)全系統(tǒng)策略文件和唯一的(可選)用戶策略文件。
首次調(diào)用缺省 Policy 對(duì)象的 getPermissions
方法或在任何時(shí)候調(diào)用 Policy 對(duì)象 refresh
方法時(shí),即對(duì)其進(jìn)行初始化。初始化包括分析策略配置文件(請(qǐng)參閱策略文件語法)及組裝 Policy 對(duì)象。
如前所述,系統(tǒng)在缺省情況下具有單個(gè)全系統(tǒng)策略文件和唯一的用戶策略文件。
系統(tǒng)策略文件的缺省位置為:
java.home/lib/security/java.policy (Solaris)
java.home\lib\security\java.policy (Windows)
注意: java.home 指的是名為“java.home”的系統(tǒng)屬性的值,它指定 JDK 的安裝目錄。
系統(tǒng)策略文件可用于授予全系統(tǒng)代碼權(quán)限。與 JDK 一起安裝的 java.policy
文件可向標(biāo)準(zhǔn)擴(kuò)展 (Java standard extensions) 授予全部權(quán)限,允許任何用戶在無特權(quán)要求的端口進(jìn)行監(jiān)聽,同時(shí)允許任何代碼讀取某些對(duì)安全不敏感的“標(biāo)準(zhǔn)”屬性(例如“os.name”和“file.separator”屬性)。
用戶策略文件的缺省位置為:
user.home/.java.policy (Solaris)
user.home\.java.policy (Windows)
注意: user.home 指的是名為“user.home”的系統(tǒng)屬性的值,它指定用戶的主目錄。在 Windows 系統(tǒng)中,假定用戶名是 uName,“user.home”屬性的缺省值為:
C:\Winnt\Profiles\uName(多用戶 Windows NT 系統(tǒng)中)
C:\Windows\Profiles\uName(多用戶 Windows 95 系統(tǒng)中)
C:\Windows(單用戶 Windows 95 系統(tǒng)中)
初始化 Policy 時(shí),將首先加載系統(tǒng)策略,然后在 Policy 中添加用戶策略。如果兩種策略均不存在,則采用內(nèi)置策略。該內(nèi)置策略與原始的沙箱策略相同。
策略文件的位置在安全屬性文件中指定。安全屬性文件的位置為:
java.home/lib/security/java.security (Solaris)
java.home\lib\security\java.security (Windows)
如上所述,java.home 指示 JDK 的安裝目錄。策略文件的位置被指定為其名稱具有以下形式的屬性的值:
policy.url.n
其中 n 為數(shù)字。應(yīng)采用以下形式的語句行來指定每個(gè)屬性值:
policy.url.n=URL
其中,URL 為 URL 規(guī)范。
例如,安全屬性文件中將把缺省系統(tǒng)和用戶策略文件定義為:
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
有關(guān)利用特殊語法(例如利用 ${java.home} 來指定 java.home 屬性值)來指定屬性值的詳細(xì)信息,請(qǐng)參閱屬性擴(kuò)展。
實(shí)際上,用戶可以指定多個(gè) URL(包括“http://”形式的 URL),從而加載所有指定的策略文件。也可注釋掉或更改第二個(gè) URL,從而禁止讀取缺省用戶策略文件。
該算法自 policy.url.1 開始,然后不斷遞增直到查不到 URL 為止。因此,如果有了 policy.url.1 和 policy.url.3,就不會(huì)讀取 policy.url.3。
運(yùn)行時(shí)指定其它策略文件
在執(zhí)行應(yīng)用程序時(shí)也可以指定附加的或不同的策略文件,方法是用“-Djava.security.policy”命令行參數(shù)來指定(該命令行參數(shù)設(shè)置 java.security.policy 屬性值)。例如,如果使用
java -Djava.security.manager -Djava.security.policy=someURL SomeApp
這里 someURL 是指定策略文件位置的 URL,則除了加載安全屬性文件中指定的所有策略文件外,還會(huì)加載本方法所指定的策略文件。
注意:
如果使用
java -Djava.security.manager -Djava.security.policy==someURL SomeApp
(請(qǐng)注意雙等號(hào)),就會(huì)僅使用指定的策略文件,而安全屬性文件中指出的策略文件將被忽略。
如果要將策略文件傳遞給 appletviewer,就應(yīng)使用參數(shù)“-J-Djava.security.policy”,如下所示:
appletviewer -J-Djava.security.policy=someURL myApplet
請(qǐng)注意:如果將安全屬性文件中的“policy.allowSystemProperty”屬性設(shè)置為“false”,就會(huì)忽略“-Djava.security.policy”策略文件值(對(duì)于 java
和 appletviewer
命令)。缺省值為“true”。
可以用其它 policy 類來代替缺省 Policy 實(shí)現(xiàn)類,前提是前者屬于抽象 Policy 類的子類并可實(shí)現(xiàn) getPermissions
方法(及其它必要的方法)。
缺省 Policy 實(shí)現(xiàn)的更改可通過編輯安全屬性文件來完成,其中安全屬性文件指 JDK lib/security
目錄中的 java.security
文件。
下面給出一種可在 java.security
中設(shè)置的屬性類型的形式:
policy.provider=PolicyClassName
PolicyClassName 必須指定所需 Policy 實(shí)現(xiàn)類的完整名稱。該屬性的缺省安全屬性文件項(xiàng)如下所示:
policy.provider=sun.security.provider.PolicyFile
要想自定義安全屬性文件項(xiàng),可通過更改屬性值來指定另一個(gè)類,如下例所示:
policy.provider=com.mycom.MyPolicy
JDK 的策略配置文件可用于指定來自特定代碼源的代碼所能獲得的權(quán)限(何種系統(tǒng)資源訪問類型)。
為了使 applet(或在安全管理器下運(yùn)行的應(yīng)用程序)能夠執(zhí)行受保護(hù)的動(dòng)作(例如讀寫文件),必須向 applet(或應(yīng)用程序)授予進(jìn)行該動(dòng)作的權(quán)限。在缺省 Policy 實(shí)現(xiàn)中,必須由策略配置文件中的 grant 項(xiàng)授予該權(quán)限。有關(guān)詳細(xì)信息,請(qǐng)參閱以下內(nèi)容及 “Java 安全體系結(jié)構(gòu)規(guī)范”(唯一的例外是:代碼對(duì)位于與它自身同一 (URL) 位置并且對(duì)那一位置子目錄下的文件總是自動(dòng)擁有讀權(quán)限,而無需授予明確的權(quán)限)。
策略配置文件主要包含授權(quán)項(xiàng)列表。其中可能包含“keystore”(密鑰倉庫)項(xiàng)及零個(gè)或多個(gè)“grant”(授權(quán))項(xiàng)。
Keystore 項(xiàng)
keystore 是存放私鑰及相關(guān)數(shù)字證書(例如驗(yàn)證對(duì)應(yīng)的公鑰的 X.509 證書鏈)的數(shù)據(jù)庫。keytool 實(shí)用程序 (for Solaris) (for Windows) 用于創(chuàng)建和管理密鑰倉庫。策略配置文件中所指定的 keystore 用于查找在該文件的授權(quán)項(xiàng)中所指定的簽名人公鑰。如果某一授權(quán)項(xiàng)指定了簽名人別名(請(qǐng)參閱以下內(nèi)容),則在策略配置文件中必須含有 keystore 項(xiàng)。
目前,在策略文件中只能有一個(gè) keystore 項(xiàng)(第一項(xiàng)后的其它 keystore 項(xiàng)將被忽略),且該項(xiàng)可位于文件授權(quán)項(xiàng)以外的任何位置。其語法如下所示:
keystore "some_keystore_url", "keystore_type";
其中“some_keystore_url”指定密鑰倉庫的 URL 位置,而“keystore_type”指定密鑰倉庫的類型。
URL 是相對(duì)于策略文件位置而言。因此,如果在安全屬性文件中按以下方式指定策略文件:
policy.url.1=http://foo.bar.com/fum/some.policy
而且策略文件中含有以下項(xiàng):
keystore ".keystore";
就會(huì)從下列位置加載密鑰倉庫:
http://foo.bar.com/fum/.keystore
URL 也可以是絕對(duì) URL。
keystore type 定義密鑰倉庫信息的存儲(chǔ)和數(shù)據(jù)格式,同時(shí)也定義用于保護(hù)密鑰倉庫中私鑰及密鑰倉庫自身完整性的算法。Sun Microsystems 所支持的缺省類型是名為“JKS”的專用密鑰倉庫類型。因此,如果密鑰倉庫類型屬于“JKS”,就無需在 keystore 項(xiàng)中加以指定。
授權(quán)項(xiàng)
通常認(rèn)為執(zhí)行代碼來自于某“代碼源”(由 CodeSource 類型的對(duì)象表示)。代碼源不僅包含代碼的源位置 (URL),而且還包括對(duì)包含與簽寫代碼的私鑰相對(duì)應(yīng)的公鑰的證書之引用。代碼源中的證書通過用戶密鑰倉庫中的符號(hào)別名引用。
每個(gè)授權(quán)項(xiàng)包括一個(gè)或多個(gè)“權(quán)限項(xiàng)”,前面為可選 codeBase
和 signedBy
名字/值對(duì),用于指定要授予權(quán)限的代碼。授權(quán)項(xiàng)的基本格式如下所示:
grant signedBy "signer_names", codeBase "URL" {
permission permission_class_name "target_name", "action",
signedBy "signer_names";
....
permission permission_class_name "target_name", "action",
signedBy "signer_names";
};
以上所有非斜體的項(xiàng)必須按原樣出現(xiàn)(盡管大小寫無關(guān)緊要且部分為可選項(xiàng),如下所示)。 斜體項(xiàng)代表變量值。
授權(quán)項(xiàng)必須以 grant
開頭。
SignedBy 和 CodeBase 域
signedBy
和 codeBase
名字/值對(duì)為可選域,其間的順序無關(guān)緊要。
signedBy
值表示存儲(chǔ)在密鑰倉庫中的證書別名。該證書內(nèi)的公鑰用于驗(yàn)證代碼上的數(shù)字簽名;用戶可以向由私鑰(私鑰對(duì)應(yīng)于該別名所指定的 keystore 項(xiàng)中的公鑰)簽名的代碼授予權(quán)限。
signedBy
的值可以是由逗號(hào)分隔的多個(gè)別名。 例如“Adam,Eve,Charles”,其含義為“Adam,Eve 和 Charles 簽名”;它們之間的關(guān)系是 AND(與)而非 OR(或)。更確切地說,“Adam 簽名的代碼”語句的含義是“JAR 文件中有含類文件的代碼,這個(gè) JAR 文件已用密鑰倉庫中別名為 Adam 的項(xiàng)中與公鑰所對(duì)應(yīng)的私鑰簽名”。
signedBy
域可選,這是因?yàn)槿绻÷栽撚颍瑒t表示“任何簽名人”。代碼是否有簽名或由誰簽名都沒有關(guān)系。
codeBase
值表示的是代碼源位置;用戶可向來自該位置的代碼授權(quán)。空 codeBase
項(xiàng)表示“任何代碼”;代碼來源于何處沒有關(guān)系。
注意: codeBase
值是 URL,因此應(yīng)該始終用正斜杠(而不要用反斜杠)作為目錄分隔符,即使代碼源實(shí)際在 Windows 系統(tǒng)上。這樣,如果 Windows 系統(tǒng)上代碼的源位置實(shí)際上是 C:\somepath\api\
,則 codeBase
策略項(xiàng)的外觀將如下所示:
grant codeBase "file:/C:/somepath/api/" {
...
}
codeBase
值的準(zhǔn)確含義要取決于最后的字符。后面跟著“/”的 codeBase
將匹配指定目錄下的所有類文件(非 JAR 文件)。后面跟著“/*”的 codeBase
將匹配該目錄下的所有文件(類文件和 JAR 文件)。后面跟著“/-”的 codeBase
將匹配該目錄下的所有文件(類文件和 JAR 文件)及該目錄下子目錄中的所有文件。下表說明了各種不同的情況。 下載代碼的 Codebase URL | 策略中的 Codebase URL | 是否匹配? |
---|
java.sun.com/people/gong/ | java.sun.com/people/gong | 是 |
java.sun.com/people/gong/ | java.sun.com/people/gong/ | 是 |
java.sun.com/people/gong/ | java.sun.com/people/gong/* | 是 |
java.sun.com/people/gong/ | java.sun.com/people/gong/- | 是 |
java.sun.com/people/gong/appl.jar | java.sun.com/people/gong/ | 否 |
java.sun.com/people/gong/appl.jar | java.sun.com/people/gong/- | 是 |
java.sun.com/people/gong/appl.jar | java.sun.com/people/gong/* | 是 |
java.sun.com/people/gong/appl.jar | java.sun.com/people/- | 是 |
java.sun.com/people/gong/appl.jar | java.sun.com/people/* | 否 |
java.sun.com/people/gong/ | java.sun.com/people/- | 是 |
java.sun.com/people/gong/ | java.sun.com/people/* | 否 |
權(quán)限項(xiàng)
權(quán)限項(xiàng)必須以 permission
開頭。上述模板中的字 permission_class_name
的實(shí)際值可以是特定的權(quán)限類型(例如 java.io.FilePermission
或 java.lang.RuntimePermission
)。
"action" 對(duì)于許多權(quán)限類型而言都是必需的,例如 java.io.FilePermission
(指定允許何種類型的文件訪問權(quán)限)。 對(duì)于諸如 java.lang.RuntimePermission
等權(quán)限類型則為可選項(xiàng):既可以在 permission_class_name 之后的 "target_name"
值中指定權(quán)限,也可以不指定權(quán)限。
權(quán)限項(xiàng)的 signedBy
名字/值對(duì)為可選項(xiàng)。如果有名字/值對(duì),則表示為已簽名權(quán)限。意即必須由給定的別名對(duì)權(quán)限類簽名,方可授予權(quán)限。例如,假定有以下授權(quán)項(xiàng):
grant {
permission Foo "foobar", signedBy "FooSoft";
}
如果將 Foo.class
權(quán)限放到 JAR 文件中,且該 JAR 文件已由與 "FooSoft" 別名所指定的證書中的公鑰相對(duì)應(yīng)的私鑰簽名,或在 Foo.class
是系統(tǒng)類(因?yàn)橄到y(tǒng)類不受策略限制)的情況下,即可授予 Foo 權(quán)限類型。
權(quán)限項(xiàng)中出現(xiàn)的項(xiàng)目必須按指定順序出現(xiàn)(permission
,permission_class_name,"target_name","action" 和 signedBy
"signer_names")。分號(hào)表示項(xiàng)終止。
大小寫對(duì)于標(biāo)識(shí)符(permission
、signedBy
、codeBase
等)來說并不重要,但對(duì)于 permission_class_name 或作為值傳遞過來的字符串而言就很重要了。
有關(guān) Windows 系統(tǒng)上文件路徑規(guī)范的注意事項(xiàng)
請(qǐng)注意:在指定 java.io.FilePermission
時(shí),"target_name" 是文件路徑。在 Windows 系統(tǒng)上,無論何時(shí)在字符串中(而不是在 codeBase URL 中)直接指定文件路徑,路徑中都需要兩個(gè)反斜杠來代表一個(gè)實(shí)際的反斜杠,如下例所示:
grant {
permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read";
};
原因在于:字符串是由符號(hào)處理器 (java.io.StreamTokenizer) 來處理的。符號(hào)處理器允許將“\”用作轉(zhuǎn)義字符串(例如,“\n”表示換行),因此需要用兩個(gè)反斜杠來表示一個(gè)反斜杠。符號(hào)處理器處理完以上文件路徑字符串后,將把雙反斜杠轉(zhuǎn)換成單個(gè)反斜杠,其最終結(jié)果為:
"C:\users\cathy\foo.bat"
策略配置文件中兩項(xiàng)的示例如下所示:
// 如果代碼由 "Duke" 簽字,則向 /tmp 中的所有文件
// 授予讀/寫訪問權(quán)限:
grant signedBy "Duke" {
permission java.io.FilePermission "/tmp/*", "read,write";
};
// 授予所有用戶以下權(quán)限:
grant { permission java.util.PropertyPermission "java.vendor"; };
另一個(gè)示例策略配置文件如下所示。
grant signedBy "sysadmin", codeBase "file:/home/sysadmin/*" {
permission java.security.SecurityPermission "Security.insertProvider.*";
permission java.security.SecurityPermission "Security.removeProvider.*";
permission java.security.SecurityPermission "Security.setProperty.*";
};
本示例規(guī)定:只有滿足以下條件的代碼才能調(diào)用 Security 類中的方法以添加或刪除提供者或者設(shè)置 Security 屬性:
- 代碼將從位于本地文件系統(tǒng)上“/home/sysadmin/”目錄下的簽名 JAR 文件中加載。
- 可以用密鑰倉庫中別名“sysadmin”所引用的公鑰來校驗(yàn)簽名。
可以忽略代碼源中兩個(gè)組件的任何一個(gè)(或兩者)。下面是忽略 codeBase
的示例:
grant signedBy "sysadmin" {
permission java.security.SecurityPermission "Security.insertProvider.*";
permission java.security.SecurityPermission "Security.removeProvider.*";
};
如果該策略生效,則來自 JAR 文件(由 "sysadmin" 簽名)的代碼可以添加/刪除提供者,而不管 JAR 文件來源于何處。
下面是沒有簽名人的示例:
grant codeBase "file:/home/sysadmin/-" {
permission java.security.SecurityPermission "Security.insertProvider.*";
permission java.security.SecurityPermission "Security.removeProvider.*";
};
這里,來自本地文件系統(tǒng)“/home/sysadmin/”目錄下任意位置的代碼都可以添加/刪除提供者。 該代碼不必簽名。
下面是既不含 codeBase
也不含 signedBy
的示例:
grant {
permission java.security.SecurityPermission "Security.insertProvider.*";
permission java.security.SecurityPermission "Security.removeProvider.*";
};
此處,由于兩個(gè)代碼源組件均被忽略,因此任何代碼(不管來自于何處,是否已簽名或由何人簽名)都可添加/刪除提供者。
策略文件和安全屬性文件中可以進(jìn)行屬性擴(kuò)展。
屬性擴(kuò)展類似于擴(kuò)展 shell 中的變量。也就是說,當(dāng)類似
${some.property}
的字符串出現(xiàn)在策略文件或安全屬性文件中時(shí),它將被擴(kuò)展為系統(tǒng)屬性的值。 例如,
permission java.io.FilePermission "${user.home}", "read";
將把 "${user.home}" 擴(kuò)展為使用 "user.home" 系統(tǒng)屬性的值。如果該屬性的值是 "/home/cathy",則以上示例等價(jià)于:
permission java.io.FilePermission "/home/cathy", "read";
為了能在與平臺(tái)無關(guān)的策略文件中使用,也可采用特殊記號(hào) "${/}"。該記號(hào)是 "${file.separator}" 的簡化表示。這種方式允許使用下列字符串:
permission java.io.FilePermission "${user.home}${/}*", "read";
如果 "user.home" 屬性的值是 /home/cathy
,而且是在 Solaris 系統(tǒng)上,則以上字符串將轉(zhuǎn)換為:
permission java.io.FilePermission "/home/cathy/*", "read";
如果 "user.home" 值是 C:\users\cathy
,而且是在 Windows 系統(tǒng)上,則以上字符串將轉(zhuǎn)換為:
permission java.io.FilePermission "C:\users\cathy\*", "read";
同樣,作為一種特例,如果擴(kuò)展 codebase 中的屬性,例如
grant codeBase "file:${java.home}/lib/ext/"
則任何文件分隔符都將自動(dòng)轉(zhuǎn)換為“/”。這樣,在 Windows 系統(tǒng)上,以上字符串將轉(zhuǎn)換為:
grant codeBase "file:C:/jdk1.2/lib/ext/"
即使 "java.home" 被設(shè)置為 C:\jdk1.2
。因此,用戶就不必也不應(yīng)該在 codeBase 字符串中使用 ${/}。
策略文件中允許使用雙引號(hào)字符串的地方都可進(jìn)行屬性擴(kuò)展。其中包括 "signer_names"、"URL"、"target_name" 和 "action" 域。
是否允許屬性擴(kuò)展由安全屬性文件中的“policy.expandProperties”屬性控制。如果該屬性為真(缺省值),則允許擴(kuò)展。
請(qǐng)注意:不能使用嵌套屬性;嵌套屬性將無效。 例如,
"${user.${foo}}"
是無效的,即使將“foo”屬性設(shè)置為“home”。原因在于屬性解析程序不能識(shí)別嵌套屬性;解析程序只是簡單地搜索第一個(gè)“${”,然后繼續(xù)搜索直到找到第一個(gè)“}”為止,同時(shí)試圖將搜索結(jié)果(這里是 "${user.$foo}")解釋為屬性。如果沒有這種屬性,則解析程序就會(huì)發(fā)生解釋失敗。
也請(qǐng)注意:如果在 grant 項(xiàng)、permission 項(xiàng)或 keystore 項(xiàng)中無法擴(kuò)展某個(gè)屬性,則該項(xiàng)將被忽略。例如,如果在沒有定義系統(tǒng)屬性“foo”的情況下使用語句:
grant codeBase "${foo}" {
permission ...;
permission ...;
};
則該 grant 項(xiàng)中的所有權(quán)限都將被忽略。如果使用語句:
grant {
permission Foo "${foo}";
permission Bar;
};
則將僅忽略“permission Foo...”項(xiàng)。最后,如果使用語句:
keystore "${foo}";
則將忽略 keystore 項(xiàng)。
Windows 系統(tǒng)、文件路徑和屬性的擴(kuò)展
如上所述,在 Windows 系統(tǒng)上,當(dāng)直接在字符串中(而不是在 codeBase URL 中)指定文件路徑時(shí),用戶需要用兩個(gè)反斜杠來代表文件路徑中一個(gè)實(shí)際的反斜杠,如下例所示:
grant {
permission java.io.FilePermission "C:\\users\\cathy\\foo.bat", "read";
};
原因在于:字符串是由符號(hào)處理器 (java.io.StreamTokenizer) 來處理的。符號(hào)處理器允許將“\”用作轉(zhuǎn)義字符串(例如,“\n”表示換行),因此需要用兩個(gè)反斜杠來表示一個(gè)反斜杠。符號(hào)處理器處理完以上文件路徑字符串后,將把雙反斜杠轉(zhuǎn)換成單個(gè)反斜杠,其最終結(jié)果為:
"C:\users\cathy\foo.bat"
符號(hào)處理器處理完字符串后,即進(jìn)行字符串中的屬性擴(kuò)展。因此,如果使用字符串:
"${user.home}\\foo.bat"
則符號(hào)處理器首先處理字符串,即將雙反斜杠轉(zhuǎn)換成單個(gè)反斜杠,其結(jié)果為:
"${user.home}\foo.bat"
隨即擴(kuò)展 ${user.home} 屬性,其最終結(jié)果為:
"C:\users\cathy\foo.bat"
以上假定 "user.home" 的值是 C:\users\cathy
。當(dāng)然,為實(shí)現(xiàn)與平臺(tái)無關(guān),最好在開始指定字符串時(shí)不要顯式帶上斜杠,即可以用 ${/} 屬性來代替,如下例所示:
"${user.home}${/}foo.bat"