- 論壇徽章:
- 0
|
轉(zhuǎn)載:轉(zhuǎn)載請(qǐng)保留本信息,本文來自
http://www.matrix.org.cn/resource/article/0/638.html
Extending JAAS
Guosheng Huang, PhD, is a seniorsoftware developer withWysdom Inc. He has over 15years of experience in software engineering and technical architecture. gorsenhuang@yahoo.com
翻譯:綠野風(fēng)煙 2003/10
用戶認(rèn)證和訪問控制是大多數(shù)java應(yīng)用的重要安全尺度,特別是J2EE應(yīng)用。Java認(rèn)證和權(quán)限服務(wù)(即JAAS),J2SE1.4和1.5的核心API,描繪表達(dá)了新的安全標(biāo)準(zhǔn)。其提供了一個(gè)可插拔的(pluggable)和富有彈性的(flexible)框架(framework)允許開發(fā)者混合不同的安全機(jī)制和豐富的已經(jīng)存在各種安全方面的資源。
伴隨著即將來臨的J2SE1.5版本的發(fā)布,它包含了許多諸如加密技術(shù)、XML安全性、公鑰機(jī)制(PKI)、Kerberos (是一個(gè)網(wǎng)絡(luò)附加系統(tǒng)/協(xié)議,可以允許用戶通過一個(gè)安全伺服器的服務(wù)來驗(yàn)證 自己。象遠(yuǎn)端登陸,遠(yuǎn)端拷貝,系統(tǒng)間的相互檔拷貝和另外高風(fēng)險(xiǎn)任務(wù)的服務(wù)將被變 得相當(dāng)安全和可控制。)和結(jié)盟認(rèn)證(the federating identity)的增強(qiáng)!,JAAS將會(huì)在J2EE實(shí)現(xiàn)中扮演一個(gè)更加重要的角色。
認(rèn)證
認(rèn)證就是校驗(yàn)一個(gè)用戶擁有使用已經(jīng)被企業(yè)用戶注冊(cè)機(jī)構(gòu)證明了的身份鑒定的權(quán)限的處理過程。JAAS的認(rèn)證機(jī)制建立于一整套可插拔的模塊(參看圖1)基礎(chǔ)上。JAAS允許不同的驗(yàn)證模型在運(yùn)行時(shí)可被插拔?蛻魬(yīng)用總是通過登陸上下文對(duì)象和JAAS交互。
認(rèn)證處理過程典型的要經(jīng)過下面的步驟:
1、 生成一個(gè)LoginContext對(duì)象。這個(gè)LoginContext尋找配置文件以決定使用那個(gè)LoginModule。同樣,可選擇的,有可能傳遞一個(gè)CallbackHandler給LoginContext.
2、 通過調(diào)用LoginContext的login方法執(zhí)行認(rèn)證,它會(huì)加載預(yù)定義的LoginModule去檢驗(yàn)是否用戶可以被認(rèn)證。
3、 如果用戶被認(rèn)證,那么用規(guī)則和標(biāo)識(shí)和其所屬項(xiàng)進(jìn)行關(guān)聯(lián)。
4、 或者在登陸失敗的情況下跑出一個(gè)LoginException
5、 使用LoginContext的logout方法進(jìn)行注銷登陸
在JAAS中,登陸是一個(gè)兩階段(two-phase)的處理過程。第一階段是“登陸(login)”階段(就像上面2所描述的)。這個(gè)階段唯一的任務(wù)是認(rèn)證。只要處理過程成功通過這個(gè)階段,認(rèn)證處理過程就進(jìn)入了“提交(commit)”階段(如上步驟3),這一階段LoginModule的commit方法被調(diào)用去關(guān)聯(lián)所屬子項(xiàng)相關(guān)的規(guī)則和標(biāo)識(shí)。
在JAAS中一個(gè)所屬子項(xiàng)表示一個(gè)認(rèn)證實(shí)體,比如一個(gè)人或者一臺(tái)設(shè)備。它包含了一整套法則和安全相關(guān)的屬性諸如密碼和加密密鑰。在JAAS體系結(jié)構(gòu)中,所屬子項(xiàng)和其所附屬的相關(guān)權(quán)限,扮演了重要的角色在認(rèn)證過程當(dāng)中。所有的認(rèn)證模塊當(dāng)中,LoginModule是事實(shí)上的認(rèn)證機(jī)制的借口。雖然LoginModule決沒有得到直接調(diào)用客戶應(yīng)用的機(jī)會(huì),但是他經(jīng)由一個(gè)可插拔的模塊提供了一個(gè)認(rèn)證的具體類型,其實(shí)現(xiàn)了認(rèn)證的算法并且決定實(shí)際的認(rèn)證過程是怎樣被執(zhí)行的。
SUN提供了幾個(gè)默認(rèn)的LoginModule 實(shí)現(xiàn),在sun.com.security.auth.module包里有諸如JndiLoginModule,Krb2LoginModule,UnixLoginModule和NTLoginModule等幾個(gè)LoginModule實(shí)現(xiàn)。因?yàn)镴AAS登錄結(jié)構(gòu)體系是可擴(kuò)展的,所以你只要在配置文件中指定使用哪個(gè)LoginModule模塊就可以幾乎全部插入任何LoginModule模塊。
如下即為一個(gè)配置文件的例子:
MySample {
com.sample.module.MyLoginModule required debug=true;
};
這里MySample是登錄上下文環(huán)境(login context)的名字,當(dāng)你生成一個(gè)新的LoginContext開始認(rèn)證過程時(shí)它會(huì)被傳入LoginContex的構(gòu)造函數(shù)中。依據(jù)配置塊提示,那個(gè)文本塊提醒JAAS有關(guān)LoginModule在登錄過程中應(yīng)該被用來執(zhí)行認(rèn)證。另外,對(duì)于LoginModule,任何關(guān)于他的選項(xiàng)也可以在這里被指定。在執(zhí)行登錄這一步驟的過程中,CallbackHandler類被LoginModule類用來跟用戶通信已便于取得認(rèn)證信息。CallbackHandler類處理三種類型的回調(diào)(Callback):NameCallback,提示用戶輸入一個(gè)用戶名;PasswordCallcack,提示輸入密碼;TextOutputCallback,報(bào)告錯(cuò)誤、警告或則發(fā)送給用戶一些其他信息。
授權(quán)是決定是否認(rèn)證的用戶可以執(zhí)行一些動(dòng)作的工作,例如訪問一處資源。因?yàn)镴AAS建立于已經(jīng)存在的Java安全模型的基礎(chǔ)上,故這個(gè)過程時(shí)基于策略的。策略配置文件實(shí)質(zhì)上包含了一系列的入口,諸如“Keystore”和/或“grant”.
grant入口包含了所有的權(quán)限,他是通過認(rèn)證的代碼或則法則被授予可以進(jìn)行安全敏感的操作,例如,訪問一個(gè)具體的Web頁(yè)面或則本地的文件。JAAS支持基于法則的策略入口,賦權(quán)入口基本格式如下:
grant Codebase “codebase_URL” Signedby “signer_name,”
Principal principal_class_name “principal_name”,
Principal principal_class_name “principal_name”,
… {
permission permission_class_name “target_name”, “action”,
permission permission_class_name “target_name”, “action”,
…
}
上面格式中“動(dòng)作(action)”可能是必需的或則可能被忽略依賴于權(quán)限類型。在JAAS體系結(jié)構(gòu)中,策略對(duì)象表達(dá)了一個(gè)Java應(yīng)用環(huán)境的系統(tǒng)安全策略和在任何時(shí)間事實(shí)上只有一個(gè)策略對(duì)象。依據(jù)Java2 SDK文檔,默認(rèn)的策略實(shí)現(xiàn)是sun.security.provider.PolicyFile,其中策略被指定在一個(gè)或多個(gè)策略配置文件里。
只要用戶被認(rèn)證,授權(quán)經(jīng)由Subject.doAs方法發(fā)生,或者從Subject類的靜態(tài)方法doAsPrivileged,doAS方法用當(dāng)前的AccessControlContext動(dòng)態(tài)和子項(xiàng)并且同時(shí)調(diào)用run方法去執(zhí)行動(dòng)作,他導(dǎo)致安全驗(yàn)證。權(quán)限驗(yàn)證過程通過下面的步驟在圖2:
就像LoginModule,策略也是可插拔的模型。你可以掛上其它的策略實(shí)現(xiàn)通過在java.security的屬性文件中改變“policy.provider=sun.security.provider.PolicyFile”
到一個(gè)你項(xiàng)使用的策略類。
Extend JAAS
JAAS建立于已經(jīng)存在的Java安全模型的頂端,其基于“CodeSource”和平面文本格式策略文件實(shí)現(xiàn)。這可能對(duì)企業(yè)應(yīng)用是不夠用的,你可能想使用可定制的安全倉(cāng)庫(kù)。對(duì)于JAAS的其它實(shí)現(xiàn),諸如LDAP(輕型目錄訪問協(xié)議),數(shù)據(jù)庫(kù)或者其他文件系統(tǒng),它可以通過編寫你自己的可定制模塊被完成,感謝JAAS的可插拔的特性。然而,這需要對(duì)模塊和JAAS中的處理過程有完善的理解,同時(shí)你必須做許多編碼去覆寫相關(guān)的類,并且處理好配置和策略兩種文件。
理想情況下,我們?cè)敢饽軌驍U(kuò)展JAAS以一個(gè)更加容易的方式以便于無論何時(shí)一個(gè)可定制的安全知識(shí)庫(kù)或者不同的訪問控制機(jī)制改變或者必須去增加時(shí),你能夠只開發(fā)和插入這些不同的小模塊(即,適配器)去適應(yīng)這些新的變化和需求,并且在最好的情況下,不必去理解和熟悉JAAS處理過程的細(xì)節(jié),同樣,我們也愿意能夠去做這些變化僅僅通過改變一個(gè)配置文件。另一個(gè)目標(biāo)是我們的JAAS擴(kuò)展組件能夠被使用在不同的J2EE應(yīng)用中—獨(dú)立的或者Web上的。圖3描述了JAAS擴(kuò)展組件的設(shè)計(jì)意圖。我們的JAAS擴(kuò)展組在實(shí)現(xiàn)可定制的LoginModule和策略模塊時(shí)充分件利用了JAAS插拔式的體系結(jié)構(gòu)。這些模塊中,我們委派數(shù)據(jù)請(qǐng)求到適配器。這些適配器的每個(gè)對(duì)于諸如數(shù)據(jù)取回的簡(jiǎn)單任務(wù)是隔離的,所以你可以快速地使用不同的安全知識(shí)或者算法開發(fā)不同的適配器而不是嘗試去實(shí)現(xiàn)不同的LoginModule或者策略模塊,它們更加復(fù)雜并且需要更多的努力。
你可以從www.sys-con.com/java/sourcec.cfm.下在完整的源瑪。
實(shí)現(xiàn)的AuthLoginModule類
AuthLoginModule類是我們定制的LoginModule實(shí)現(xiàn),LoginModule類是在JAAS中是一個(gè)可插拔組件并且服務(wù)于兩個(gè)目的:
1、鑒定認(rèn)證用戶
2、如果認(rèn)證成公,則用相關(guān)的負(fù)責(zé)人信息或者證書更新主題。
LoginModule有5個(gè)方法去實(shí)現(xiàn)功能,讓我們關(guān)注一下login()方法。這個(gè)方法被調(diào)用以認(rèn)證主題并且主要作兩件事情:
1、包含用戶名和密碼,典型地,LoginModule要調(diào)用CallbackHandler類的handle方法去得到用戶名和密碼
2、通過和數(shù)據(jù)源中的比較校驗(yàn)密碼。LoginModule從Callbacks取回用戶名和密碼。(其默認(rèn)期望用戶接口的某種排序),這一點(diǎn)對(duì)于一個(gè)簡(jiǎn)單的演示程序或者就在命令行,可是他對(duì)于一個(gè)J2EE應(yīng)用來說不太實(shí)用,例如,對(duì)于大多數(shù)的Web應(yīng)用,用戶名和密碼將比較典型的從一個(gè)form中讀出。在這種情況下,使用JAAS認(rèn)證會(huì)比較困難。考慮我們不直接使用LoginModule,解決方案是實(shí)現(xiàn)一個(gè)可定制的CallbackHandler類,他會(huì)接收用戶名和密碼然后遞交它們給LoginModule,所以他沒有必要提示用戶輸入信息
以下示例説明用戶信息如何從JSP或者Servlet中傳遞:
String userName = request.getParameter (“user”);
String password = request.getParameter(“password”);
LoginContext context = new LoginContext (“MySample”,
new AuthCallbackHandler (userName, password));
一旦擁有了用戶名和密碼在手,AuthLoginModule類,我們的LoginModule類的定制實(shí)現(xiàn),會(huì)經(jīng)由LoginSourceAdapterFactory實(shí)例化LoginSourceAdapter并同時(shí)委派實(shí)際的認(rèn)證過程到資源適配器。適配器只不過是一個(gè)簡(jiǎn)單的類,其從一個(gè)具體的數(shù)據(jù)適配器(比如數(shù)據(jù)庫(kù)或者LDAP,或者一些別的系統(tǒng))領(lǐng)取用戶信息。在“提交”階段,AuthLoginModule類從LoginSourceAdapter類取回相關(guān)的信息并且把他們和主題相關(guān)聯(lián)。
LoginSourceAdapter類
LoginSourceAdapter類是一個(gè)認(rèn)證目的的資源適配器的接口,它有4個(gè)需要實(shí)現(xiàn)的方法:
1、void initialize(Hashtable parameters):initialized方法被調(diào)用來以相關(guān)的參數(shù)初始化適配器。此方法在對(duì)象生成后立即被調(diào)用并且優(yōu)先于任何對(duì)其他方法的調(diào)用。
2、boolean authenticate(String username,char[] password):此認(rèn)證方法被調(diào)用來認(rèn)證用戶。
3. String[] getGroupNames (String userName):getGroupNames方法被調(diào)用來在認(rèn)證成功后得到相關(guān)的主要信息。
4. void terminate ():這個(gè)方法在LoginModule類的logout方法被執(zhí)行后調(diào)用,它給適配器做一些清理工作的機(jī)會(huì)。
AuthPolicy類
在JAAS架構(gòu)下,安全策略被java.securety.Policy 類來處理,他會(huì)證明賦給一個(gè)具體的代碼源或者主體的多種權(quán)限。就像在上一段被討論的,sun.securety.provider.PolicyFile是其默認(rèn)實(shí)現(xiàn)。PolicyFile類使用平面文本文件去證明在權(quán)限和代碼源之間的對(duì)應(yīng)關(guān)系,這點(diǎn)對(duì)于企業(yè)級(jí)應(yīng)用可能不是太好。一個(gè)集中的系統(tǒng)比如支持基于角色的安全性的關(guān)系數(shù)據(jù)庫(kù)將會(huì)更好。很明顯,擴(kuò)展JAAS授權(quán)以處理不同的來源的不同的安全標(biāo)記,我們需要寫我們自己的策略實(shí)現(xiàn)。
生成一個(gè)定制的策略實(shí)現(xiàn)的步驟如下:
•擴(kuò)展java.securety.Policy類
•實(shí)現(xiàn)getPermissions()方法
•實(shí)現(xiàn)refresh()方法.
如果你看到我們定制的策略類的實(shí)現(xiàn),你可能注意到我們的AuthPolicy類派生在sun.security.provider.PolicyFile而不是java.security.Policy. 為什么?首先,我想要實(shí)現(xiàn)AuthPolicy類作為通用的Policy類,這可以處理默認(rèn)的策略類不需要用任何適配器介入。通過從PolicyFile類,我們不需要去實(shí)現(xiàn)策略文件解析和其他相關(guān)的代碼。同時(shí),黨應(yīng)用運(yùn)行于一個(gè)安全管理器起作用的情況下,一些權(quán)限,比如doAsPrivileged AuthPermission類和讀入配置文件的FilePermission(為了載入配置文件),需要被賦權(quán)為了執(zhí)行JAAS.
當(dāng)然,這些權(quán)限可以被存儲(chǔ)在數(shù)據(jù)源里,但是把它們放入標(biāo)準(zhǔn)Java安全策略文件中可能更為有利。可是,對(duì)于正規(guī)開發(fā)你應(yīng)該實(shí)現(xiàn)一個(gè)適配器以應(yīng)付這些事情。在擴(kuò)展認(rèn)證時(shí)要遵循相同的設(shè)計(jì)模式。我們的策略類委托權(quán)限請(qǐng)求于
PermisssionAdapter類
在權(quán)限類里,不同的權(quán)限保存于自己的PermissionCollection類實(shí)例,如果你創(chuàng)建一個(gè)定制的權(quán)限類,你需要生成你自己的PermissionCollection類類型,否則不能保證你的權(quán)限對(duì)象將被參考確認(rèn)。
PermissionAdapter類
PermissionAdapter類在我們的JAAS擴(kuò)展組件中是認(rèn)證過程可插拔模塊的接口。它從一個(gè)具體的數(shù)據(jù)源評(píng)估策略并且分發(fā)一個(gè)包含一套已賦予的權(quán)限的PermissionCollection類。PermissionAdapter類接口有下面的方法:
• void initialize (Hashtable initParams):initialize方法被調(diào)用以相關(guān)的參數(shù)初始化適配器。此方法會(huì)被立即調(diào)用并且優(yōu)先于任何其它的方法調(diào)用。同時(shí),在Policy類的refresh方法被執(zhí)行后它也會(huì)被調(diào)用。
• PermissionCollection getPermissions (ProtectionDomain
domain): 本方法只要某種主體權(quán)限被請(qǐng)求就會(huì)被調(diào)用。
作為一例子,讓我們看看如何實(shí)現(xiàn)一個(gè)基于角色的PermissionAdapter類。假設(shè)有三個(gè)角色:管理員,用戶,和客人,都擁有不同的權(quán)限,并且所有的權(quán)限信息被存儲(chǔ)在數(shù)據(jù)庫(kù)中。
首先,在initialize方法中,我們將從數(shù)據(jù)中取得所有角色的權(quán)限信息并且組裝入集合類中,比如,Hashtable.接下來,在getPermissions方法中,我們會(huì)收集到相關(guān)主體有關(guān)的權(quán)限(這是僅有的會(huì)涉及到基于角色的訪問控制)并且返回它們。注意我們可以得到相關(guān)的主體通過調(diào)用ProtectedDomain類的getPrincipals方法。它是如此的簡(jiǎn)單,不是嗎?
JaasUtil類
對(duì)于我們的JAAS擴(kuò)展組件JaasUtil類是主要的紐帶,并且它有一個(gè)構(gòu)造函數(shù)取得用戶名和密碼。有兩個(gè)關(guān)鍵的方法:
1. boolean authenticate()
2. boolean checkPermission(Subject subject,final Permission perm)
JaasUtil類實(shí)際延遲了LoginContext類的登陸請(qǐng)求和SecurityManager類的權(quán)限檢查步驟。 Listing 1 顯示了如何使用JaasUtil類。這段代碼首先從HtttpServletRequest類取得用戶名和密碼并且嘗試認(rèn)證用戶.然后其檢測(cè)是否用戶有權(quán)限訪問“editReg.jsp”.
配置
現(xiàn)在我們擁有自己的定制的LoginModule,Policy和其他相關(guān)模塊實(shí)現(xiàn)。這些模塊可以委托相關(guān)的數(shù)據(jù)請(qǐng)求給合適的適配器;這是很好的事情。然而,在JAAS結(jié)構(gòu)中LoginModule類和Policy類絕對(duì)不會(huì)被應(yīng)用程序直接調(diào)用,所以我們?cè)鯓又滥欠N適配器應(yīng)該被實(shí)力化和怎樣傳遞需要的參數(shù)或者信息,比如數(shù)據(jù)連接,給適配器?答案是適配器可以通過更新一個(gè)XML配置文件被動(dòng)態(tài)配置。這個(gè)XML配置文件由兩個(gè)主要的數(shù)據(jù)段組成:
1、:本段內(nèi)容定義登陸源適配器和認(rèn)證過程需要的各種可能的輸入?yún)?shù)。
2、:本段內(nèi)容定義權(quán)限適配器和授權(quán)過程序要的各種可能的輸入?yún)?shù)
你可以制定使用哪個(gè)LoginSourceAdapter類和PermissionAdapter類。在配置文件中傳遞額外的信息也是可能的。讓JaasUtil類知道在那里尋找配置文件有兩種途徑:
1、 制定配置文件經(jīng)由命令行屬性開關(guān): -Dcon.auth.config
2、 調(diào)用JaasUtil.setConfigFile(configFile)方法.
當(dāng)你部署JAAS擴(kuò)展組件時(shí),這個(gè)定制安全策略類文件必須被加入到Java的jre/lib目錄,這將引起策略類文件被bootstrap類加載其載入。否則,即便你放置策略文件在你的Java類路徑中,它也將不能被檢出并且Sun默認(rèn)提供的策略類將會(huì)代替而被使用。
總結(jié)
擴(kuò)展JAAS是不困難的。JAAS結(jié)構(gòu)提供給你定制實(shí)現(xiàn)認(rèn)證和授權(quán)過程的彈性。理解這些過程如何工作是懂得如何替換你自己的實(shí)現(xiàn)的第一步。在本文中,我們重溫JAAS的基礎(chǔ),并且檢查驗(yàn)證了如何擴(kuò)展JAAS使其成為一個(gè)更加具備動(dòng)態(tài)化、靈活化和規(guī)模化的特性的框架。使用這種擴(kuò)展框架,你既能夠輕松的生成自己登陸和訪問控制機(jī)制以支持你自己的企業(yè)級(jí)別的安全需求也能夠支持新興的安全標(biāo)準(zhǔn),或者平衡你們已經(jīng)存在的或定制安全模型作為適配器,然后熱插拔他們進(jìn)入JAAS中。這應(yīng)該可以給你的企業(yè)應(yīng)用提供一個(gè)基于標(biāo)準(zhǔn)的同時(shí)高可定制的認(rèn)證和授權(quán)過程。
References
• JAAS Reference Guide for the Java 2 SDK, Standard Edition,
v 1.4: http://java.sun.com/j2se/1.4.1/docs/guide/security/
jaas/JAASRefGuide.html#Policy
• JAAS LoginModule Developer Guide:
http://java.sun.com/j2se/1.4.1/docs/guide/security/jaas/
JAASLMDevGuide.html#login
• Lai, C., et al. “User Authentication and Authorization in
Java Platform.” Proceedings of the 15th Annual Computer
Security Application Conference, Phoenix, AZ. December
1999: http://java.sun.com/security/jaas/doc/acsac.html
• Sun Microsystems, Inc. “Default Policy Implementation
and Policy File Syntax.” Technical report:
http://java.sun.com/j2se/1.4.1/docs/guide/security/Policy
Files.html
本文來自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u/5834/showart_226856.html |
|