“Java 認(rèn)證和授權(quán)服務(wù)”(Java Authentication and Authorization Service,JAAS)是對(duì) Java 2 SDK 的擴(kuò)展。在 JAAS 下,可以給予用戶或服務(wù)特定的許可權(quán)來執(zhí)行 Java 類中的代碼。在本文中,軟件工程師 Carlos Fonseca 向您展示如何為企業(yè)擴(kuò)展 JAAS 框架。向 JAAS 框架添加類實(shí)例級(jí)授權(quán)和特定關(guān)系使您能夠構(gòu)建更動(dòng)態(tài)、更靈活并且伸縮性更好的企業(yè)應(yīng)用程序。請(qǐng)單擊文章頂部或底部的 討論,在 討論論壇與作者和其他讀者分享您對(duì)本文的想法。
大多數(shù) Java 應(yīng)用程序都需要某種類實(shí)例級(jí)的訪問控制。例如,基于 Web 的、自我服務(wù)的拍賣應(yīng)用程序的規(guī)范可能有下列要求:
任何已注冊(cè)(經(jīng)過認(rèn)證)的用戶都可以創(chuàng)建一個(gè)拍賣,但只有創(chuàng)建拍賣的用戶才可以修改這個(gè)拍賣。
這意味著任何用戶都可以執(zhí)行被編寫用來創(chuàng)建 Auction
類實(shí)例的代碼,但只有擁有該實(shí)例的用戶可以執(zhí)行用來修改它的代碼。通常情況下,創(chuàng)建 Auction
實(shí)例的用戶就是所有者。這被稱為 類實(shí)例所有者關(guān)系(class instance owner relationship)。
該應(yīng)用程序的另一個(gè)要求可能是:
任何用戶都可以為拍賣創(chuàng)建一個(gè)投標(biāo),拍賣的所有者可以接受或拒絕任何投標(biāo)。
再一次,任何用戶都可以執(zhí)行被編寫用來創(chuàng)建 Bid
類實(shí)例的代碼,但只有擁有該實(shí)例的用戶會(huì)被授予修改該實(shí)例的許可權(quán)。而且, Auction
類實(shí)例的所有者必須能夠修改相關(guān)的 Bid
類實(shí)例中的接受標(biāo)志。這意味著在 Auction
實(shí)例和相應(yīng)的 Bid
實(shí)例之間有一種被稱為 特定關(guān)系(special relationship)的關(guān)系。
不幸的是,“Java 認(rèn)證和授權(quán)服務(wù)”(JAAS)― 它是 Java 2 平臺(tái)的一部分 ― 沒有考慮到類實(shí)例級(jí)訪問控制或者特定關(guān)系。在本文中,我們將擴(kuò)展 JAAS 框架使其同時(shí)包含這兩者。推動(dòng)這種擴(kuò)展的動(dòng)力是允許我們將訪問控制分離到一個(gè)通用的框架,該框架使用基于所有權(quán)和特定關(guān)系的策略。然后管理員可以在應(yīng)用程序的生命周期內(nèi)更改這些策略。
在深入到擴(kuò)展 JAAS 框架之前,我們將重溫一下 Java 2 平臺(tái)的訪問控制機(jī)制。我們將討論策略文件和許可權(quán)的使用,并討論 SecurityManager
和 AccessController
之間的關(guān)系。
Java 2 平臺(tái)中的訪問控制
在 Java 2 平臺(tái)中,所有的代碼,不管它是本地代碼還是遠(yuǎn)程代碼,都可以由策略來控制。 策略(policy)由不同位置上的代碼的一組許可權(quán)定義,或者由不同的簽發(fā)者定義、或者由這兩者定義。 許可權(quán)允許對(duì)資源進(jìn)行訪問;它通過名稱來定義,并且可能與某些操作關(guān)聯(lián)在一起。
抽象類 java.security.Policy
被用于表示應(yīng)用程序的安全性策略。缺省的實(shí)現(xiàn)由 sun.security.provider.PolicyFile
提供,在 sun.security.provider.PolicyFile
中,策略被定義在一個(gè)文件中。清單 1 是一個(gè)典型策略文件示例:
清單 1. 一個(gè)典型的策略文件
// Grant these permissions to code loaded from a sample.jar file
// in the C drive and if it is signed by XYZ
grant codebase "file:/C:/sample.jar", signedby "XYZ" {
// Allow socket actions to any host using port 8080
permission java.net.SocketPermission "*:8080", "accept, connect,
listen, resolve";
// Allows file access (read, write, execute, delete) in
// the user's home directory.
Permission java.io.FilePermission "${user.home}/-", "read, write,
execute, delete";
};
|
SecurityManager 對(duì) AccessController
在標(biāo)準(zhǔn) JDK 分發(fā)版中,控制代碼源訪問的機(jī)制缺省情況下是關(guān)閉的。在 Java 2 平臺(tái)以前,對(duì)代碼源的訪問都是由 SecurityManager
類管理的。 SecurityManager
是由 java.security.manager
系統(tǒng)屬性啟動(dòng)的,如下所示:
java -Djava.security.manager
|
在 Java 2 平臺(tái)中,可以將一個(gè)應(yīng)用程序設(shè)置為使用 java.lang.SecurityManager
類或者 java.security.AccessController
類管理敏感的操作。 AccessController
在 Java 2 平臺(tái)中是新出現(xiàn)的。為便于向后兼容, SecurityManager
類仍然存在,但把自己的決定提交 AccessController
類裁決。 SecurityManager
和 AccessController
都使用應(yīng)用程序的策略文件確定是否允許一個(gè)被請(qǐng)求的操作。清單 2 顯示了 AccessController
如何處理 SocketPermission
請(qǐng)求:
清單 2. 保護(hù)敏感操作
Public void someMethod() {
Permission permission =
new java.net.SocketPermission("localhost:8080", "connect");
AccessController.checkPermission(permission);
// Sensitive code starts here
Socket s = new Socket("localhost", 8080);
}
|
在這個(gè)示例中,我們看到 AccessController
檢查應(yīng)用程序的當(dāng)前策略實(shí)現(xiàn)。如果策略文件中定義的任何許可權(quán)暗示了被請(qǐng)求的許可權(quán),該方法將只簡單地返回;否則拋出一個(gè) AccessControlException
異常。在這個(gè)示例中,檢查實(shí)際上是多余的,因?yàn)槿笔√捉幼謱?shí)現(xiàn)的構(gòu)造函數(shù)也執(zhí)行相同的檢查。
在下一部分,我們將更仔細(xì)地看一下 AccessController
如何與 java.security.Policy
實(shí)現(xiàn)共同合作安全地處理應(yīng)用程序請(qǐng)求。
運(yùn)行中的 AccessController
AccessController
類典型的 checkPermission(Permission p)
方法調(diào)用可能會(huì)導(dǎo)致下面的一系列操作:
-
AccessController
調(diào)用 java.security.Policy
類實(shí)現(xiàn)的 getPermissions(CodeSource codeSource)
方法。
-
getPermissions(CodeSource codeSource)
方法返回一個(gè) PermissionCollection
類實(shí)例,這個(gè)類實(shí)例代表一個(gè)相同類型許可權(quán)的集合。
-
AccessController
調(diào)用 PermissionCollection
類的 implies(Permission p)
方法。
- 接下來,
PermissionCollection
調(diào)用集合中包含的單個(gè) Permission
對(duì)象的 implies(Permission p)
方法。如果集合中的當(dāng)前許可權(quán)對(duì)象暗示指定的許可權(quán),則這些方法返回 true
,否則返回 false
。
現(xiàn)在,讓我們更詳細(xì)地看一下這個(gè)訪問控制序列中的重要元素。
PermissionCollection 類
大多數(shù)許可權(quán)類類型都有一個(gè)相應(yīng)的 PermissionCollection
類。這樣一個(gè)集合的實(shí)例可以通過調(diào)用 Permission
子類實(shí)現(xiàn)定義的 newPermissionCollection()
方法來創(chuàng)建。 java.security.Policy
類實(shí)現(xiàn)的 getPermissions()
方法也可以返回 Permissions
類實(shí)例 ― PermissionCollection
的一個(gè)子類。這個(gè)類代表由 PermissionCollection
組織的不同類型許可權(quán)對(duì)象的一個(gè)集合。 Permissions
類的 implies(Permission p)
方法可以調(diào)用單個(gè) PermissionCollection
類的 implies(Permission p)
方法。
CodeSource 和 ProtectionDomain 類
許可權(quán)組合與 CodeSource
(被用于驗(yàn)證簽碼(signed code)的代碼位置和證書)被封裝在 ProtectionDomain
類中。有相同許可權(quán)和相同 CodeSource
的類實(shí)例被放在相同的域中。帶有相同許可權(quán),但不同 CodeSource
的類被放在不同的域中。一個(gè)類只可屬于一個(gè) ProtectionDomain
。要為對(duì)象獲取 ProtectionDomain
,請(qǐng)使用 java.lang.Class
類中定義的 getProtectionDomain()
方法。
許可權(quán)
賦予 CodeSource
許可權(quán)并不一定意味著允許所暗示的操作。要使操作成功完成,調(diào)用棧中的每個(gè)類必須有必需的許可權(quán)。換句話說,如果您將 java.io.FilePermission
賦給類 B,而類 B 是由類 A 來調(diào)用,那么類 A 必須也有相同的許可權(quán)或者暗示 java.io.FilePermission
的許可權(quán)。
在另一方面,調(diào)用類可能需要臨時(shí)許可權(quán)來完成另一個(gè)擁有那些許可權(quán)的類中的操作。例如,當(dāng)從另一個(gè)位置加載的類訪問本地文件系統(tǒng)時(shí),我們可能不信任它。但是,本地加載的類被授予對(duì)某個(gè)目錄的讀許可權(quán)。這些類可以實(shí)現(xiàn) PrivilegedAction
接口來給予調(diào)用類許可權(quán)以便完成指定的操作。調(diào)用棧的檢查在遇到 PrivilegedAction
實(shí)例時(shí)停止,有效地將執(zhí)行指定操作所必需的許可權(quán)授予所有的后繼類調(diào)用。
使用 JAAS
顧名思義,JAAS 由兩個(gè)主要組件組成:認(rèn)證和授權(quán)。我們主要關(guān)注擴(kuò)展 JAAS 的授權(quán)組件,但開始我們先簡要概述一下 JAAS 認(rèn)證,緊接著看一下一個(gè)簡單的 JAAS 授權(quán)操作。
JAAS 中的用戶認(rèn)證
JAAS 通過添加基于 subject 的策略加強(qiáng)了 Java 2 中定義的訪問控制安全性模型。許可權(quán)的授予不僅基于 CodeSource
,還基于執(zhí)行代碼的用戶。顯然,要使這個(gè)模型生效,每個(gè)用戶都必須經(jīng)過認(rèn)證。
JAAS 的認(rèn)證機(jī)制建立在一組可插登錄模塊的基礎(chǔ)上。JAAS 分發(fā)版包含幾個(gè) LoginModule
實(shí)現(xiàn)。 LoginModules
可以用于提示用戶輸入用戶標(biāo)識(shí)和密碼。 LoginContext
類使用一個(gè)配置文件來確定使用哪個(gè) LoginModule
對(duì)用戶進(jìn)行認(rèn)證。這個(gè)配置可以通過系統(tǒng)屬性 java.security.auth.login.config
指定。一個(gè)示例配置是:
java -Djava.security.auth.login.config=login.conf
|
下面是一個(gè)登錄配置文件的樣子:
Example {
com.ibm.resource.security.auth.LoginModuleExample required
debug=true userFile="users.xml" groupFile="groups.xml";
};
|
認(rèn)識(shí)您的主體
Subject
類被用于封裝一個(gè)被認(rèn)證實(shí)體(比如用戶)的憑證。一個(gè) Subject
可能擁有一個(gè)被稱為 主體(principal)的身份分組。例如,如果 Subject
是一個(gè)用戶,用戶的名字和相關(guān)的社會(huì)保險(xiǎn)號(hào)可能是 Subject
的某些身份或主體。主體是與身份名關(guān)聯(lián)在一起的。
Principal
實(shí)現(xiàn)類及其名稱都是在 JAAS 策略文件中指定的。缺省的 JAAS 實(shí)現(xiàn)使用的策略文件與 Java 2 實(shí)現(xiàn)的策略文件相似 ― 除了每個(gè)授權(quán)語句必須與至少一個(gè)主體關(guān)聯(lián)在一起。 javax.security.auth.Policy
抽象類被用于表示 JAAS 安全性策略。它的缺省實(shí)現(xiàn)由 com.sun.security.auth.PolicyFile
提供,在 com.sun.security.auth.PolicyFile
中策略定義在一個(gè)文件中。清單 3 是 JAAS 策略文件的一個(gè)示例:
清單 3. 示例 JAAS 策略文件
// Example grant entry
grant codeBase "file:/C:/sample.jar", signedby "XYZ",
principal com.ibm.resource.security.auth.PrincipalExample "admin" {
// Allow socket actions to any host using port 8080
permission java.net.SocketPermission
"*:8080", "accept, connect, listen, resolve";
// Allows file access (read, write, execute, delete) in
// the user's home directory.
Permission java.io.FilePermission
"${user.home}/-", "read, write, execute, delete";
};
|
這個(gè)示例與清單 1 中所示的標(biāo)準(zhǔn) Java 2 策略文件相似。實(shí)際上,唯一的不同是主體語句,該語句聲明只有擁有指定主體和主體名字的 subject(用戶)被授予指定的許可權(quán)。
再一次,使用系統(tǒng)屬性 java.security.auth.policy
指出 JAAS 策略文件駐留在何處,如下所示:
java -Djava.security.auth.policy=policy.jaas
|
Subject
類包含幾個(gè)方法來作為特殊 subject 執(zhí)行工作;這些方法如下所示:
public static Object
doAs(Subject subject, java.security.PrivilegedAction action)
public static Object
doAs(Subject subject, java.security.PrivilegedAction action)
throws java.security.PrivilegedActionException
|
注意,用來保護(hù)敏感代碼的方法與“Java 2 代碼源訪問控制”(Java 2 CodeSource Access Control)概述中描述的方法相同。請(qǐng)參閱 參考資料部分以了解更多關(guān)于 JAAS 中代碼源訪問控制和認(rèn)證的信息。
JAAS 中的授權(quán)
清單 4 顯示一個(gè)授權(quán)請(qǐng)求的結(jié)果,該請(qǐng)求使用清單 3 中顯示的 JAAS 策略文件。假設(shè)已經(jīng)安裝了 SecurityManager
,并且 loginContext
已經(jīng)認(rèn)證了一個(gè)帶有名為“admin”的 com.ibm.resource.security.auth.PrincipalExample
主體的 Subject
。
清單 4. 一個(gè)簡單的授權(quán)請(qǐng)求
public class JaasExample {
public static void main(String[] args) {
...
// where authenticatedUser is a Subject with
// a PrincipalExample named admin.
Subject.doAs(authenticatedUser, new JaasExampleAction());
...
}
}
public class JaasExampleAction implements PrivilegedAction {
public Object run() {
FileWriter fw = new FileWriter("hi.txt");
fw.write("Hello, World!");
fw.close();
}
}
|
這里,敏感代碼被封裝在 JaasExampleAction
類中。還要注意,調(diào)用類不要求為 JaasExampleAction
類代碼源授予許可權(quán),因?yàn)樗鼘?shí)現(xiàn)了一個(gè) PrivilegedAction
。
擴(kuò)展 JAAS
大多數(shù)應(yīng)用程序都有定制邏輯,它授權(quán)用戶不僅僅在類上執(zhí)行操作,而且還在該類的實(shí)例上執(zhí)行操作。這種授權(quán)通常建立在用戶和實(shí)例之間的關(guān)系上。這是 JAAS 的一個(gè)小缺點(diǎn)。然而,幸運(yùn)的是,這樣設(shè)計(jì) JAAS 使得 JAAS 可以擴(kuò)展。只要做一點(diǎn)工作,我們將可以擴(kuò)展 JAAS,使其包含一個(gè)通用的、類實(shí)例級(jí)的授權(quán)框架。
在文章開頭處我已經(jīng)說明了,抽象類 javax.security.auth.Policy
被用于代表 JAAS 安全性策略。它的缺省實(shí)現(xiàn)是由 com.sun.security.auth.PolicyFile
類提供。 PolicyFile
類從 JAAS 格式的文件(象清單 3 中顯示的那個(gè)一樣)中讀取策略。
我們需要向這個(gè)文件添加一個(gè)東西為類實(shí)例級(jí)授權(quán)擴(kuò)展策略定義:一個(gè)與許可權(quán)語句相關(guān)的可選關(guān)系參數(shù)。
缺省 JAAS 許可權(quán)語句的格式如下:
permission <permission implementation class> [name], [actions];
|
我們?cè)谶@個(gè)許可權(quán)語句的末尾添加一個(gè)可選的關(guān)系參數(shù)來完成策略定義。下面是新許可權(quán)語句的格式:
permission <permission implementation class>
[name], [actions], [relationship];
|
在為類實(shí)例級(jí)授權(quán)擴(kuò)展 JAAS 時(shí)要注意的最重要的一點(diǎn)是:許可權(quán)實(shí)現(xiàn)類必須有一個(gè)帶三個(gè)參數(shù)的構(gòu)造函數(shù)。第一個(gè)參數(shù)是名稱參數(shù),第二個(gè)是行為參數(shù),最后一個(gè)是關(guān)系參數(shù)。
解析新文件格式
既然文件格式已經(jīng)改變,就需要一個(gè)新的 javax.security.auth.Policy
子類來解析文件。
為簡單起見,我們的示例使用了一個(gè)新的 javax.security.auth.Policy
子類 com.ibm.resource.security.auth.XMLPolicyFile
,來從 XML 文件讀取策略。在實(shí)際的企業(yè)應(yīng)用程序中,關(guān)系數(shù)據(jù)庫更適合執(zhí)行這個(gè)任務(wù)。
使用 XMLPolicyFile
類代替缺省的 JAAS 訪問控制策略實(shí)現(xiàn)的最容易的方法是向 java.security
屬性文件添加 auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile
條目。 java.security
屬性文件位于 Java 2 平臺(tái)運(yùn)行時(shí)的 lib/security 目錄下。清單 5 是與 XMLPolicyFile
類一起使用的樣本 XML 策略文件:
清單 5. 一個(gè) XML 策略文件
<?xml version="1.0"?>
<policy>
<grant codebase="file:/D:/sample_actions.jar">
<principal classname=
"com.ibm.resource.security.auth.PrincipalExample" name="users">
<permission classname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Auction"
actions="create" />
<permission classname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Auction"
actions="read" />
<permission classname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Auction"
actions="write"
relationship="owner" />
<permission classname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Bid"
actions="create" />
<permission classname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Bid"
actions="read" />
<permission classname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Bid"
actions="write"
relationship="owner" />
<permission classname=
"com.ibm.resource.security.auth.ResourcePermission"
name="com.ibm.security.sample.Bid"
actions="accept"
relationship="actionOwner" />
</principal>
</grant>
</policy>
|
在這個(gè)示例策略文件中,任何與名為 PrincipalExample
的用戶有關(guān)的用戶( Subject
)都可以創(chuàng)建并讀取一個(gè) Auction.class
實(shí)例。但是,只有創(chuàng)建該實(shí)例的用戶才可以更新(寫)它。這是第三個(gè) permission 元素定義的,該元素包含值為 owner 的 relationship 屬性。 Bid.class
實(shí)例也是一樣,除了相應(yīng) Auction.class
實(shí)例的所有者可以更改投標(biāo)接受標(biāo)志。
Resource 接口
要求類實(shí)例級(jí)訪問控制的類必須實(shí)現(xiàn) Resource
接口。該接口的 getOwner()
方法返回類實(shí)例的所有者。 fulfills(Subject subject, String relationship)
方法被用于處理特定關(guān)系。另外,這些類使用 com.ibm.resource.security.auth.ResourcePermission
類保護(hù)敏感代碼。例如, Auction
類擁有下列構(gòu)造函數(shù):
public Auction() {
Permission permission =
new ResourcePermission("com.ibm.security.sample.Auction", "create");
AccessController.checkPermission(permission);
}
|
所有者關(guān)系
ResourcePermission
類的 implies(Permission p)
方法是這個(gè)框架的關(guān)鍵。 implies()
方法就等同性比較名稱和行為屬性。如果定義了一個(gè)關(guān)系,那么必須把受保護(hù)的類實(shí)例( Resource
)傳遞到 ResourcePermission
構(gòu)造函數(shù)中。 ResourcePermission
類理解所有者關(guān)系。它將類實(shí)例的所有者與執(zhí)行代碼的 subject(用戶)進(jìn)行比較。特定關(guān)系被委托給受保護(hù)類的 fulfills()
方法。
例如,在清單 5 中所示的 XML 策略文件中,只有 Auction
類實(shí)例的所有者可以更新(寫)文件。該類的 setter 方法使用清單 6 中顯示的保護(hù)代碼:
清單 6. 運(yùn)行中的 implies(Permission) 方法
public void setName(String newName) {
Permission permission =
new ResourcePermission("com.ibm.security.sample.Auction", "write", this);
AccessController.checkPermission(permission);
// sensitive code
this.name = newName;
}
|
被傳遞到 ResourcePermission
構(gòu)造函數(shù)中的 this
引用代表 Auction
類實(shí)現(xiàn)的 Resource
接口。由于策略文件中列出的關(guān)系是 owner,所以 ResourcePermission
類使用這個(gè)引用檢查當(dāng)前 Subject
(用戶)是否擁有與實(shí)例所有者相匹配的主體。如果指定了另一個(gè)關(guān)系,那么 ResourcePermission
類調(diào)用 Auction
類的 fulfills(Subject subject, String relationship)
方法。由 Resource
實(shí)現(xiàn)類提供 fulfills()
方法中的邏輯。
XML 策略文件中列出的 Bid
類擁有清單 7 中所示的方法(假設(shè) Bid
類實(shí)例有一個(gè)對(duì)相應(yīng) Auction
類實(shí)例的引用 ― auction)。
清單 7. 處理特定關(guān)系
public void setAccepted(boolean flag) {
Permission permission =
new ResourcePermission("com.ibm.security.sample.Auction", "accept", this);
AccessController.checkPermission(permission);
// sensitive code
this.accepted = flag;
}
public boolean fulfills(Subject user, String relationship) {
if( relationship.equalsIgnoreCase("auctionOwner") ) {
String auctionOwner = auction.getOwner();
Iterator principalIterator = user.getPrincipals().iterator();
while(principalIterator.hasNext()) {
Principal principal = (Principal) principalIterator.next();
if( principal.getName().equals(auctionOwner) )
return true;
}
}
return false;
}
|
傳遞到 fulfills()
方法中的關(guān)系字符串是策略文件中列出的關(guān)系。在這個(gè)案例中,我們使用了“ auctionOwner
”字符串。
缺省情況下, XMLPolicyFile
類在當(dāng)前工作目錄中查找名為 ResourcePolicy.xml
的文件。系統(tǒng)屬性 com.ibm.resource.security.auth.policy
可以用于指定另一個(gè)不同的文件名和位置。
一個(gè)可運(yùn)行的示例
綜合這些信息,我們將運(yùn)行一個(gè)簡單的命令行示例。該示例程序包含三個(gè) jar 文件:
- resourceSecurity.jar
- example.jar
- exampleActions.jar
resourceSecurity.jar 文件包含允許實(shí)例級(jí)訪問控制的 JAAS 擴(kuò)展框架。它還包含一個(gè) LoginModuleExample
類,這個(gè)類從 XML 文件讀取用戶認(rèn)證信息。用戶標(biāo)識(shí)和密碼存儲(chǔ)在 users.xml 文件中。用戶組存儲(chǔ)在 groups.xml 文件中。關(guān)于 LoginModuleExample
的更多信息,請(qǐng)參閱 參考資料部分。
該示例包含四個(gè)附加的文件:
- login.conf
- policy
- resourcePolicy.xml
- run.bat
在試圖運(yùn)行這個(gè)示例程序之前,請(qǐng)確保更新了 run.bat、policy 和 resourcePolicy.xml 文件中的路徑。缺省情況下,所有的密碼都是“passw0rd”。
示例如何工作
該示例程序提示輸入用戶標(biāo)識(shí)和密碼。它用 users.xml 文件中的條目核對(duì)所提供的用戶標(biāo)識(shí)和密碼。在認(rèn)證了用戶之后,程序設(shè)法創(chuàng)建一個(gè) UserProfile
類實(shí)例,修改它并從中讀取。缺省情況下, UserProfile
類的所有者是 Jane(jane)。當(dāng) Jane 登錄時(shí),三個(gè)操作全部成功。當(dāng) John(john)登錄時(shí),只有創(chuàng)建操作成功。當(dāng) Jane 的經(jīng)理 Lou(lou)登錄時(shí),只有第一個(gè)和最后一個(gè)操作成功。當(dāng)系統(tǒng)管理員(admin)登錄時(shí),操作全部成功。當(dāng)然,只有當(dāng)提供的 ResourcePolicy.xml 文件未被修改時(shí),上述這些才都是真的。
示例安裝
下面的安裝指導(dǎo)假設(shè)您正在使用 JDK 1.3 并且已經(jīng)把文件解壓縮到 d:\JaasExample 目錄。通過將文件解壓縮到這個(gè)目錄,您可以省去一些工作;否則您就必須使用正確的路徑名修改 policy 和 ResourceSecurity.xml 策略文件。
下面是運(yùn)行該示例需要做的工作:
- 下載這個(gè)示例的 源文件。
- 把 jaas.jar 和 jaasmod.jar 復(fù)制到 JDK jre\lib\ext 目錄(即 D:\JDK1.3\jre\lib\ext)。
- 向位于 JDK 的 jre\lib\security 目錄(即 D:\JDK1.3\jre\lib\security)中的 java.security 文件的末尾添加下面的字符串:
auth.policy.provider=com.ibm.resource.security.auth.XMLPolicyFile
。
- 執(zhí)行 run.bat 文件。
結(jié)束語
類實(shí)例級(jí)授權(quán)把訪問控制分離到一個(gè)通用框架(該框架使用基于所有權(quán)和特定關(guān)系的策略)中。然后管理員可以在應(yīng)用程序的生命周期內(nèi)更改這些策略。用這種方法擴(kuò)展 JAAS 減少了您或另一個(gè)程序員必須在應(yīng)用程序生命周期內(nèi)業(yè)務(wù)規(guī)則發(fā)生更改時(shí)重寫代碼的可能性。
通過將關(guān)系字符串抽象為類可以進(jìn)一步擴(kuò)展特定關(guān)系這個(gè)概念。不調(diào)用 Resource
實(shí)現(xiàn)類的 fulfills(Subject user, String relationship)
方法,而只要調(diào)用 Relationship
實(shí)現(xiàn)類中定義的新 fulfills(Subject user, Resource resource)
方法。這樣就會(huì)允許許多 Resource
實(shí)現(xiàn)類使用相同的關(guān)系邏輯。