Posted on 2007-03-07 13:00
云自無(wú)心水自閑 閱讀(1648)
評(píng)論(0) 編輯 收藏 所屬分類:
Java 、
心得體會(huì) 、
Acegi
??? Acegi提供了一個(gè)優(yōu)秀的基于J2EE企業(yè)級(jí)應(yīng)用的安全認(rèn)證機(jī)制。尤其是對(duì)于Spring框架的支持,在J2EE的企業(yè)軟件開(kāi)發(fā)解決方案中是領(lǐng)先的。
??? 來(lái)看一下Acegi的重要的共享組件。如果組件是框架的核心而且一旦缺少這些組件框架將無(wú)法運(yùn)轉(zhuǎn),那么這些組件可以稱為是“共享”的。這些Java類型是系統(tǒng)其他部分的基礎(chǔ),所以理解他們是十分重要的,雖然你可以并不會(huì)直接與之互動(dòng)。
??? 其中最基礎(chǔ)的對(duì)象是SecurityContextHolder,用于存儲(chǔ)應(yīng)用安全上下文的細(xì)節(jié)信息。缺省情況下,SecurityContextHolder使用ThreadLocal來(lái)存儲(chǔ)信息,這意味著安全上下文對(duì)于同一個(gè)線程的所有方法都是有效的。有一些應(yīng)用不適合使用ThreadLocal,比如:一個(gè)Swing的客戶端可能希望所有JVM所有的線程都使用相同的安全上下文。對(duì)于這種情況,你可以用SecurityContextHolder.MODE_GLOBAL。你可以把SecurityContextHolder從缺省模式MODE_THREADLOCAL改變?yōu)镸ODE_GLOBAL。
??? 在SecurityContextHolder中存儲(chǔ)了與應(yīng)用互動(dòng)的規(guī)則。Acegi使用Authentication對(duì)象來(lái)表示這些信息。這并不是需要你自己創(chuàng)建Authentication對(duì)象,更通常的做法是查詢到一個(gè)Authentication對(duì)象。舉例如下,在應(yīng)用的任何一個(gè)地方都可以這樣使用:
Object obj = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if( obj instanceof UserDetails){
?String username=((UserDetails)obj).getUsername();
}else{
?String username=obj.toString();
}
??? 上面這段代碼介紹了不少有意思的對(duì)象和關(guān)系。首先,大家會(huì)發(fā)現(xiàn)在SecurityContextHolder和Authentication之間存在著一個(gè)即時(shí)對(duì)象:SecurityContext,SecurityContextHolder.GetContext()返回的類型就是SecurityContext。Acegi有數(shù)個(gè)SecurtiyContext的實(shí)現(xiàn)。
??? 另一個(gè)值得注意的是我們從Authentication中獲得了一個(gè)規(guī)則。這個(gè)規(guī)則的類型是:Object。大多數(shù)情況下,我們可以把它強(qiáng)制性轉(zhuǎn)換成UserDetails對(duì)象。UserDetails是Acegi的核心接口。它代表了一種規(guī)則,但是經(jīng)過(guò)了應(yīng)用相關(guān)的擴(kuò)展。可以把UserDetails想象成為應(yīng)用數(shù)據(jù)庫(kù)與Acegi的SecurityContextHolder需要的兩者之間的適配器(Adapter)。如果作為應(yīng)用自己的數(shù)據(jù)庫(kù)的代表,那么可以把UserDetails強(qiáng)制性轉(zhuǎn)換為其原始類,這樣,你就可以調(diào)用其中的業(yè)務(wù)方法(比如:getEmail()等等)。
??? 那么,為什么要提供一個(gè)UserDetails對(duì)象呢?是這樣的:有一個(gè)特殊的接口:UserDetailsService,這個(gè)接口只有一個(gè)方法,這個(gè)方法接收一個(gè)String類型的表示用戶名的參數(shù),返回UserDetails對(duì)象。大多數(shù)認(rèn)證提供provider裝配一個(gè)代理到UserDetailsService上。UserDetailsService被用于創(chuàng)建SecurityContextHolder中存儲(chǔ)的Authentication對(duì)象。Acegi中提供了若干個(gè)UserDetailsService的實(shí)現(xiàn),一個(gè)使用內(nèi)存Map,一個(gè)用JDBC。大多數(shù)用戶傾向于寫一個(gè)自己的實(shí)現(xiàn),通常是使用DAO。不論UserDetailsService返回的是什么,都可以通過(guò)SecurityContextHolder獲得。
??? Authentication提供另一個(gè)重要的方法是getAuthorites()。這個(gè)方法返回一個(gè)GrantedAuthority對(duì)象的數(shù)組。GrantedAuthority是授權(quán)給的認(rèn)證。這個(gè)認(rèn)證通常指的是“角色”,比如:ROLE_ADMINISTRATOR或者ROLE_HR_SUPERVISOR。這些角色需配置用于web認(rèn)證,方法認(rèn)證和域?qū)ο笳J(rèn)證。如果Acegi的其他部分希望看到這些認(rèn)證,那么UserDetailsService返回GrantedAuthority對(duì)象即可。
??? 最后,有時(shí)你需要在HTTP requests之間傳遞SecurityContext,有時(shí)每次請(qǐng)求都需要重新認(rèn)證。那么可以使用HttpSessionContextIntergrationFilter,這是用于在HTTP Request之間傳遞SecurityContext的東東。就象名稱所表示的那樣:HttpSession用于存儲(chǔ)這些信息。但是你不需要直接操作HttpSession。