JAAS(Java 认证和授权服务)
傳統(tǒng)的JAVA安全機(jī)制沒有提供必要的架構(gòu)支持傳統(tǒng)的認(rèn)證和授權(quán);在J2SE里的安全是基于公鑰密碼體系和代碼簽名。也就是說,認(rèn)證是基于在JVM里執(zhí)行代碼的思想,并且沒有對資源請求提供策略。而且授權(quán)也是基于這樣的概念--代碼試圖去使用一個計算機(jī)資源。Java認(rèn)證和授權(quán)服務(wù)(JAAS)也就被設(shè)計成去應(yīng)付這些缺點(diǎn)。
JAAS使用基于用戶的的訪問控制增加了這個已經(jīng)存在的基于代碼的訪問控制機(jī)制,也提高了認(rèn)證能力。這樣你賦予的權(quán)限不僅是什么代碼在運(yùn)行,而且可以是誰在運(yùn)行它。這篇文章:
- 討論基于代碼的認(rèn)證的缺點(diǎn)
- 提供JAAS的概覽
- 展示了一個加強(qiáng)的代碼的認(rèn)證例子
- 展示了一個加強(qiáng)的代碼的授權(quán)例子
- 給予了在開發(fā)認(rèn)證和授權(quán)服務(wù)時調(diào)用成功的感覺。
- 提供了能夠適應(yīng)與你所擁有的應(yīng)用程序的簡單代碼
- 提供了一個開始學(xué)習(xí)JAAS的指導(dǎo)
目的
傳統(tǒng)的操作系統(tǒng)(例如UNIX)通過多種challenge-response機(jī)制對主體或?qū)嶓w進(jìn)行認(rèn)證。用戶名和密碼組合是屬于最常見的了。這種技術(shù)也被用來使用HTTP基本認(rèn)證方案保護(hù)資源。無論怎樣,challenge可以做得更復(fù)雜:例如,可以加密信息或者依賴與特定信息的持有者(比如媽咪的小名或者一個所選問題的答案)。然后基于這種challenge類型的響應(yīng)必須是有效的。
此外,大多數(shù)操作系統(tǒng)在一個實體或主體上的和資源列表上的基本授權(quán)是授予實體或主體去使用。例如,當(dāng)一個用戶嘗試讀或者寫一個文件時,授權(quán)機(jī)制就會去驗證當(dāng)前正在執(zhí)行的主體是否有權(quán)限去訪問這個資源。
JAAS概覽
JAAS分為2個部分:認(rèn)證(authentication)和授權(quán)(authorization). 也就是說,認(rèn)證和授權(quán)兩個都可以使用。
?
- 對于認(rèn)證用戶可以安全地決定誰正在執(zhí)行代碼,即使代碼是一個單獨(dú)的應(yīng)用程序、一個applet、一個企業(yè)級JavaBean或者一個servlet。
- 對于用戶的授權(quán),可以確認(rèn)他們是否有必要的權(quán)限去執(zhí)行他們的操作。
認(rèn)證是基于Plugable Authentication Modules(PAMs)(可插入認(rèn)證模型),它使用一個框架,用于客戶端和服務(wù)端。,認(rèn)證部分是一個使用存在于J2SE中策略文件的認(rèn)證方案的擴(kuò)展。在一個可插入的方式中執(zhí)行認(rèn)證使Java應(yīng)用程序可以去依賴于底層的安全機(jī)制。這樣做有個優(yōu)點(diǎn),就是新的或者修正的認(rèn)證機(jī)制可以方便地插入,而不用對應(yīng)用程序本身做修改。
授權(quán)是一個基于存在的策略文件的機(jī)制的擴(kuò)展,基于策略文件的機(jī)制被用作指定一個應(yīng)用程序(或可執(zhí)行代碼)能或者不能做什么操作。它是基于保護(hù)域的。也就是說,這種機(jī)制授權(quán)基于代碼來自哪里,而不是基于誰在執(zhí)行代碼。用JAAS permissions或者訪問控制不僅能控制在運(yùn)行什么代碼,也能控制誰正在運(yùn)行它。
注意:JAAS在J2SE 1.3.x是作為一個可選的包,但是到J2SE 1.4 已經(jīng)被完全整合了。
java.security.Policy API已經(jīng)被更新了,能夠在策略文件里支持基于主體的查詢和基于主體的授權(quán),等下你就可以看到
使用JAAS認(rèn)證(Authentication)
客戶端通過一個LoginContext對象與JAAS相互作用,這個LoginContext對象提供了一種開發(fā)應(yīng)用程序的方式,它不依賴于底層的認(rèn)證技術(shù)。LoginContext是javax.security.auth.login包里的一個類,它描述了用于驗證對象(subjects)的方法。Subject就是在某個你想去認(rèn)證和分配訪問權(quán)限的系統(tǒng)里的一個標(biāo)識。一個主體(subject)可能是一個用戶、一個進(jìn)程或者是一臺機(jī)器,它用javax.security.auth.Subject類表示。由于一個Subject可能涉及多個授權(quán)(一個網(wǎng)上銀行密碼和另一個電子郵件系統(tǒng)),java.security.Principal就被用作在那些關(guān)聯(lián)里的標(biāo)識。也就是說,該P(yáng)rincipal接口是一個能夠被用作代表某個實體、公司或者登陸ID的抽象概念。一個Subject可能包含多個Principles. 稍后將有一個示例類實現(xiàn)了這個Principal接口。
LoginContext對象調(diào)用負(fù)責(zé)實現(xiàn)和執(zhí)行認(rèn)證的LoginModules。LoginModule接口(在javax.security.auth.spi 包里)必須讓認(rèn)證技術(shù)的提供者去實現(xiàn),并且能夠被應(yīng)用程序指定提供一個特定認(rèn)證類型。LoginContext用來讀取Configuaration和實例化特定的LoginModules.
Configuaration被某個特定的應(yīng)用程序用作指定認(rèn)證技術(shù)或者LoginModule。因此,不同的LoginModules能夠被應(yīng)用到某個應(yīng)用程序而不用對這個應(yīng)用程序做任何的代碼修改。
簡單代碼1展示了一個簡單的JAAS客戶端。我已經(jīng)使用了要調(diào)用LoginModules的LoginContext去執(zhí)行認(rèn)證,并且用"WeatherLogin"這個名字實例化了LoginContext, 還回調(diào)了"MyCallbackHandler"(實現(xiàn)見簡單代碼2)處理程序。這個名字在配置文件里將被用作索引,決定應(yīng)該使用哪個LoginModule. 當(dāng)你看這個配置文件(見簡單代碼5)后會變得更加清楚?;卣{(diào)處理程序傳給了底層的LoginModule,因此他們能夠通過提示用戶名/密碼同用戶進(jìn)行交流和作用,例如:通過文本或者圖形用戶接口。一旦LoginContext已經(jīng)被實例化了,login方法就被調(diào)用去登陸。
簡單代碼1:MyClient.java
一個基于JAAS的應(yīng)用程序?qū)崿F(xiàn)了CallbackHandler接口,因此它能夠提示用戶去輸入特定的認(rèn)證信息,比如用戶名或者密碼,或者顯示錯誤或者警告信息。底層安全服務(wù)可能要求通過傳遞單個的callbacks到回調(diào)處理程序?;趥鬟f的callbacks,回調(diào)處理程序決定怎樣去獲取和顯示信息。例如,如果底層服務(wù)需要一個用戶名和密碼認(rèn)證一個用戶,它可以使用NameCallback和PasswordCallback. 其他的callbacks類都在javax.security.auth.callback里,包括:
?
- ChoiceCallback (顯示一個選擇列表)
- ConfirmationCallback (詢問 YES/NO, OK/CANCEL)
- LanguageCallback (用作區(qū)域化的Locale)
- TextInputCallback (獲取普通的文本信息)
- TextOutputCallback (顯示信息,警告和錯誤信息)
實現(xiàn)CallbackHandler接口意味著你需要實現(xiàn)handler方法,以獲取或者顯示在提供的callbacks里要求的信息。簡單代碼2是一個簡單的實現(xiàn)。注意在這里我使用NameCallback與用戶關(guān)聯(lián)。
簡單代碼2:MyCallbackHandler.java
現(xiàn)在,我們看一個LoginModule的簡單實現(xiàn)。注意在真實的應(yīng)用程序開發(fā)中,我們不必要自己去實現(xiàn)LoginMoudule。我們可以使用第三方的login模型并把他們應(yīng)用到我們的程序。例如,Sum Microsystems 提供了幾個LoginModule,包括:JndiLoginModule、KeyStoreLoginModule、Krb5LoginModule、NTLoginModule、UNIXLoginModule. 如果你愿意學(xué)習(xí)怎樣去使用這些login模型,請查看本文的參考信息部分。
無論怎樣,簡單代碼3展示了一個LoginModule簡單的實現(xiàn). 這個例子是非常簡單的,因為他僅僅有一個認(rèn)證字符串和一個Principal "SunnyDay", 兩個都是硬編碼。如果去login,系統(tǒng)將顯示"What is the weather like today?", 如果答案是"Sunny", 用戶就能通過。注意MyCallbackHandler是怎樣被用在login方法里的。除了login方法,你必須實現(xiàn)其他四個方法:initialize, commit, abort, and logout. 這些方法將被LoginContext用在接下來的流程里。
?
- initialize: 這個方法的目的就是用有關(guān)的信息去實例化這個LoginModule。如果login成功,在這個方法里的Subject就被用在存儲Principals和Credentials.? 注意這個方法有一個能被用作輸入認(rèn)證信息的CallbackHandler。在這個例子里,我沒有用CallbackHandler. CallbackHandler是有用的,因為它從被用作特定輸入設(shè)備里分離了服務(wù)提供者。
- login: 請求LoginModule去認(rèn)證Subject. 注意此時Principal還沒有被指定。
- commit: 如果LoginContext的認(rèn)證全部成功就調(diào)用這個方法。
- abort: 通知其他LoginModule供應(yīng)者或LoginModule模型認(rèn)證已經(jīng)失敗了。整個login將失敗。
- logout: 通過從Subject里移除Principals和Credentials注銷Subject。
(注意:出于格式考慮,這篇文章的一些界線和例子代碼已經(jīng)被分割了)。
簡單代碼3:WeatherLoginModule.java
正如你從簡單代碼3里所看到的,一個ExamplePrincipal類正在被使用。這個類是Principal接口的一個實現(xiàn)。
簡單代碼4展示了Principal接口的一個實現(xiàn)。
簡單代碼4:ExamplePrincipal.java
正如我前面提及的,LoginContext通過讀取Configuration去決定那個LoginModule將被使用。login配置文件可以是一個文件或者是數(shù)據(jù)庫。當(dāng)前Sun Microsystems默認(rèn)的實現(xiàn)是一個文件。一個login配置文件包含一個或者多個實體,這些實體指出了那些認(rèn)證技術(shù)應(yīng)該被擁有應(yīng)用程序。簡單代碼5展示了一個login配置文件。
簡單代碼5:example.conf
在這個配置文件里,實體名"WeatherLogin"就是被MyClient.java用作關(guān)聯(lián)這個實體的名字。這里的這個實體指出WeatherLoginModule應(yīng)該被用作執(zhí)行認(rèn)證。為了使整個認(rèn)證成功,這個模型(module)的認(rèn)證必須是成功的。用戶輸入了正確的信息就是成功的。
運(yùn)行例子程序
?
??? 你應(yīng)該可以看到下面的輸出(粗體文本是用戶輸入的)。
????? What is the weather like today??gloomy
???? Authentication failed. Login Failure: all modules ignored
??? 在用正確的輸入運(yùn)行客戶端:
???? What is the weather like today??Sunny
???? Authentication succeeded
?
安全管理器
在上面的例子里,默認(rèn)是沒有運(yùn)行在安全管理器下的,因此所有操作都是允許的。為了保護(hù)資源,可以使用下面的命令去運(yùn)行在安全管理器下:
你可以看到拋出了一個異常。默認(rèn)的安全管理器不允許任何操作,因此login上下文沒有被創(chuàng)建。要允許這些操作,你必須創(chuàng)建一個安全策略(安全策略是一個賦予代碼能不能執(zhí)行的權(quán)限的文本文件。簡單代碼6展示了一個簡單的安全策略。目標(biāo)createLoginContext使MyClient能夠?qū)嵗粋€login上下文。目標(biāo)modifyPrincipals允許WeatherLoginModule用一個Principal去構(gòu)造一個Subject.
簡單代碼6:policy.txt
現(xiàn)在你就能夠使用下面的命令來運(yùn)行了,注意雙等號(==)是用來覆蓋默認(rèn)安全策略的。
prompt>java -Djava.security.manager -Djava.security.policy==policy.txt
-Djava.security.auth.login.config==example.conf MyClient
What is the weather like today??Sunny
Authentication succeeded
? 注意:LoginModule的實現(xiàn)代碼和應(yīng)用程序代碼也可以放在一個jar文件里。更多相關(guān)信息,請看LoginModule Developer's Guide.
使用JAAS授權(quán)(Authorization)
JAAS授權(quán)繼承了以代碼為中心的JAVA安全體系結(jié)構(gòu)(它使用一個安全策略指定什么樣的訪問權(quán)限授予執(zhí)行中的代碼。例如,在簡單代碼6的安全策略里,所有當(dāng)前目錄的的代碼都被授權(quán);不管代碼有沒有簽名,或者誰在運(yùn)行這些代碼。JAAS也繼承了以用戶為中心(user-centric)的訪問控制。許可權(quán)的賦予不僅是正在運(yùn)行什么代碼,而且也看誰在運(yùn)行它。很快你將看到許可權(quán)能夠在策略文件里被賦予去指定principals。
為了使用JAAS授權(quán):
基于這個,ExamplePrincipal.java, WeatherLoginModule.java和 example.conf文件仍然是同一個。
為了使客戶端能夠賦予用戶權(quán)限,一旦認(rèn)證成功(用戶已經(jīng)被認(rèn)證了),認(rèn)證了的主體就使用通過Subject subject=ctx.getSubject()來獲取。然后通過傳遞給Subject.doAsPrivileged()一個認(rèn)證了的主體和一個特權(quán)行動以及空AccessControlContext去調(diào)用它。這些改變在簡單代碼7是用高亮標(biāo)識的。注意一旦執(zhí)行了認(rèn)證過程,我就調(diào)用ctx.logout是用戶退出。
簡單代碼7: MyClient.java
你可以看到,我們傳遞了一個action給doAsPrivileged,action就是用戶被授權(quán)去執(zhí)行的行為。簡單代碼8展示了MyAction.java, 它通過提供run方法的代碼實現(xiàn)了PrivilegedAction接口,run方法包含了所有將用基于principal的認(rèn)證檢查的代碼。現(xiàn)在,當(dāng)執(zhí)行doAsPrivileged方法時,它就會反過來調(diào)用在PrivilegedAction里的方法,去實例化主體其他方面剩余代碼的執(zhí)行。
在這個例子里,action就是去檢查文件"max.txt"存在于當(dāng)前的目錄。
簡單代碼8:MyAction.java
現(xiàn)在我需要更新policy.txt文件。簡單代碼9展示了這些更改。
簡單代碼9:policy.txt
現(xiàn)在當(dāng)你運(yùn)行這個應(yīng)用程序,它將首先執(zhí)行認(rèn)證。如果認(rèn)證失敗,應(yīng)用程序就停止,否則它將繼續(xù)去檢查這個文件。看下面簡單的運(yùn)行:
prompt>java -Djava.security.manager -Djava.security.policy==policy.txt//
-Djava.security.auth.login.config==example.conf MyClient
What is the weather like today??sunny
Authentication failed
prompt>java -Djava.security.manager -Djava.security.policy==policy.txt//
-Djava.security.auth.login.config==example.conf MyClient
What is the weather like today??Sunny
Authentication succeeded
The file does not exist in the current working directory
創(chuàng)建一個"max.txt"文件后再運(yùn)行下這個客戶端。
結(jié)束語
JAAS是一個能夠認(rèn)證和強(qiáng)制執(zhí)行用戶訪問控制的服務(wù)的API集合。JAAS認(rèn)證使用可插入的方式,它不依賴與底層的認(rèn)證技術(shù);JAAS授權(quán)使用以用戶為中心的訪問控制和認(rèn)證能力提高了以原本以代碼為中心的JAVA安全體系。
轉(zhuǎn)自:?https://www.iteye.com/blog/lyb520320-720478
總結(jié)
以上是生活随笔為你收集整理的JAAS(Java 认证和授权服务)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++类的构造函数 后单冒号加基类 例如
- 下一篇: 深入理解C++对象模型-对象的内存布局,