---- 在企業(yè)內(nèi)部網(wǎng)中,本文提出了使用安全策略文件來設(shè)置java程序權(quán)限的一種簡單的方法。由于企業(yè)內(nèi)部網(wǎng)中各臺計(jì)算機(jī)的位置、用途和安全性明確,更適于使用安全策略文件來設(shè)置java的權(quán)限,軟件的安裝、設(shè)置、升級和遷移都非常的方便,并且,還可以和數(shù)字簽名配合使用,更重要的是,可以細(xì)分每個java程序的權(quán)限,使用起來靈活方便。

---- Java應(yīng)用程序環(huán)境的安全策略,詳細(xì)說明了對于不同的代碼所擁有的不同資源的許可,它由一個Policy對象來表達(dá)。為了讓applet(或者運(yùn)行在SecurityManager下的一個應(yīng)用程序)能夠執(zhí)行受保護(hù)的行為,例如讀寫文件,applet(或Java應(yīng)用程序)必須獲得那項(xiàng)操作的許可,安全策略文件就是用來實(shí)現(xiàn)這些許可。
---- Policy對象可能有多個實(shí)體,雖然任何時候只能有一個起作用。當(dāng)前安裝的Policy對象,在程序中可以通過調(diào)用getPolicy方法得到,也可以通過調(diào)用setPolicy方法改變。Policy對象評估整個策略,返回一個適當(dāng)?shù)腜ermissions對象,詳細(xì)說明那些代碼可以訪問那些資源。
---- 策略文件可以儲存在無格式的ASCII文件,或Policy類的二進(jìn)制文件,或數(shù)據(jù)庫中。本文僅討論無格式的ASCII文件的形式。

---- 為了能夠更好地理解下面的內(nèi)容,建議在閱讀時參照\jdk1.2\jre\lib\security\java.policy文件和\jdk1.2\jre\lib\security\java.security文件的內(nèi)容。
---- 1. Policy文件的語法格式與說明
---- 一個Policy文件實(shí)質(zhì)上是一個記錄列表,它可能含有一個“keystore”記錄,以及含有零個或多個“grant”記錄。其格式如下:
keystore "some_keystore_url",
"keystore_type";
grant [SignedBy "signer_names"]
[, CodeBase "URL"] {
Permission permission_class_name
[ "target_name" ]
[, "action"] [, SignedBy "signer_names"];
Permission ...
};
---- 1.1"keystore"記錄
---- 一個keystore是一個私有密鑰(private keys)數(shù)據(jù)庫和相應(yīng)的數(shù)字簽名,例如X.509證書。Policy文件中可能只有一條keystore記錄(也可能不含有該記錄),它可以出現(xiàn)在文件中g(shù)rant記錄以外的任何地方。Policy配置文件中指定的keystores用于尋找grant記錄中指定的、簽名者的公共密鑰(public keys),如果任何grant記錄指定簽名者(signer_names),那么,keystore記錄必須出現(xiàn)在policy配置文件中。
---- "some_keystore_url"是指keystore的URL位置,"keystore_type"是指keystore的類型。第二個選項(xiàng)是可選項(xiàng),如果沒有指定,該類型則假定由安全屬性文件(java.security)中的"keystore.type"屬性來確定。keystore類型定義了keystore信息的存儲和數(shù)據(jù)格式,用于保護(hù)keystore中的私有密鑰和keystore完整性的算法。Sun Microsystems支持的缺省類型為“JKS”。
---- 1.2"grant"記錄
---- 在Policy文件中的每一個grant記錄含有一個CodeSource(一個指定的代碼)及其permission(許可)。
---- Policy文件中的每一條grant記錄遵循下面的格式,以保留字“grant”開頭,表示一條新的記錄的開始,“Permission”是另一個保留字,在記錄中用來標(biāo)記一個新的許可的開始。每一個grant記錄授予一個指定的代碼(CodeBase)一套許可(Permissions)。
---- permission_class_name必須是一個合格并存在的類名,例如java.io.FilePermission,不能使用縮寫(例如,F(xiàn)ilePermission)。
---- target_name用來指定目標(biāo)類的位置,action用于指定目標(biāo)類擁有的權(quán)限。
---- target_name可以直接指定類名(可以是絕對或相對路徑),目錄名,也可以是下面的通配符:
directory/* 目錄下的所有文件
*當(dāng)前目錄的所有文件
directory/-目錄下的所有文件,包括子目錄
- 當(dāng)前目錄下的所有文件,包括子目錄
《ALL FILES》文件系統(tǒng)中的所有文件
對于java.io.FilePermission,action可以是:
read, write, delete和execute。
對于java.net.SocketPermission,action可以是:
listen,accept,connect,read,write。
---- 1.3 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";

---- 當(dāng)初始化Policy時,首先裝載系統(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í)際使用中,我們可能不會象上面介紹的那么復(fù)雜,特別是在不使用數(shù)字簽名時。這時,我們完全可以借鑒JDK 1.2提供給我們的現(xiàn)成的\jdk1.2\jre\lib\security\java.policy文件,根據(jù)我們的需要作相應(yīng)的修改,本文就針對不使用數(shù)字簽名情況詳細(xì)說明安全策略文件的用法。
---- 下面,是一個完整的在Windows 95/98/NT下使用的.java.policy文件。在文件中,分別使用注釋的形式說明了每個“permission”記錄的用途。
// For LanServerTalk.java and LanClientTalk.java
grant {
//對系統(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";
//對線程和線程組的操作權(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";
};

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