<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    張昊

    J-Hi(http://www.j-hi.net)

      BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
      45 Posts :: 1 Stories :: 110 Comments :: 0 Trackbacks

    首先描述最簡單的身份驗證后臺的處理過程

    1、 用戶輸入需要確認(rèn)自己身份的信息,如賬號與密碼或許需要其它信息

    2、 也許你希望提供多種有方式的驗證形式,由系統(tǒng)選擇最合適的那一種,如從數(shù)據(jù)庫(DAO)或是通過身份驗證中心的服務(wù)(ACS)統(tǒng)一管理等

    3、 根據(jù)賬號找到指定源中的用戶、密碼及所擁有的權(quán)限(如果沒找到就拋出異常)等用戶的身份信息,驗證用戶輸入的信息與源中返回的信息是否一致(如密碼)

    4、 為了不至于每次都重復(fù)上面的過程,還要將驗證后的信息緩存起來,如放到session

    acegi結(jié)合分析

    1、 用戶提交后為了能進(jìn)行上述的處理,acegi不是通過請求-影響模式,而是能過ServletFilter實現(xiàn)的。可以理解成這個身份驗證的主入口,不同的處理機(jī)制采用不同的Filter,類名的規(guī)則為*ProcessingFilter,這些類全部都繼承至javax.servlet.Filter接口。下面是幾個常用的過濾器

    模塊

    功能

    BasicProcessingFilter

    按照RFC1945處理基本的身份驗證請求

    CasProcessingFilter

    處理耶魯大學(xué)的中心身份驗證服務(wù)器(CAS)許可

    AnonymousProcessingFilter

    對匿名身份的處理

    AuthenticationProcessingFilter

    處理類似于Servlet規(guī)范的j_security_checkHttp form post

    Spring的配置過程中有些過濾器除了自身的信息外,還有可能需要切入點,以便切入到其它模塊中的配置信息。如AuthenticationProcessingFilter驗證不通過的處理頁面或要采用的協(xié)議、CasProcessingFilter需要提交到CAS上的其他信息。它們的統(tǒng)一接口類為AuthenticationEntryPoint在此要注意的是,切入點與過濾器之間有著密切的聯(lián)系與對應(yīng)關(guān)系的。

    2、 acegi為了實現(xiàn)多種方式的驗證形式提供了AuthenticationManager接口,目的是對多種驗證形式進(jìn)行管理,并通過指定的驗證形式返回用戶的身份。所以上述的過濾器均會調(diào)用該接口的authenticate(Authentication authentication)方法以返回當(dāng)前用戶的身份信息。該接口主要的實現(xiàn)類是ProviderManager

    AuthenticationProvider(身份驗證供應(yīng)器)接口有很多實現(xiàn)類,每個都致力于處理一個特定身份驗證的具體實現(xiàn),AuthenticationManager負(fù)責(zé)輪詢AuthenticationProvider列表,并使用第一個能夠處理給定的Authentication請求對象的AuthenticationProvider。身份驗證供應(yīng)器也就是上面說的驗證形式。最常用的是DaoAuthenticationProvider,實現(xiàn)從數(shù)據(jù)庫中獲取用戶的身份信息

    3、 acegi中用戶的身份信息存放到以Authentication接口的實現(xiàn)類的實例中。在介紹該接口之前先要了解一些關(guān)鍵術(shù)語

    1) principal(主體)指可以執(zhí)行操作的用戶、服務(wù)或代理(agent),即身份驗證的發(fā)啟者

    2) credential(憑證)指主體提供密碼之類用于身份驗證(authentication)的信息戳

    3) authentication(身份驗證)確定調(diào)用者身份的過程

    4) authorization(授權(quán))指決定哪個主體準(zhǔn)許執(zhí)行給定操作的過程

    Authentication接口包含主體標(biāo)示、主體的憑證以及主體所擁有的一組權(quán)限。

    Authentication接口繼承java.security.Principal接口,因此Authentication天生就要滿足主體的類型。該接口實際上是上述幾個關(guān)鍵詞對象化的一個容器,它存儲了身份驗證的全部信息。由此會發(fā)現(xiàn)它與AuthenticationProvider(身份驗證供應(yīng)器)有著天然的聯(lián)系,如對于數(shù)據(jù)庫的供應(yīng)器它只要記錄用戶的帳號和密碼,但對于CAS它還可能還要記錄服務(wù)器響應(yīng)的列表,或是與認(rèn)證相關(guān)的其它信息。因此該接口對應(yīng)身份驗證供應(yīng)器有多個實現(xiàn)類。正因為于此,所有的實現(xiàn)類對于開發(fā)者來說幾乎是隱藏在,可以理解成工具或是服務(wù)類

    下面對Authentication接口中的方法做詳細(xì)擴(kuò)展說明

    1) getPrincipal(獲得主體)getCredential(獲得憑證),它們的設(shè)置過程:無論何種驗證形式用戶都是通過用戶輸入帳號和密碼開始的,過濾器會攔截用戶的請求,由驗證管理器(AuthenticationManager)找到合適的身份驗證供應(yīng)器(AuthenticationProvider)提供身份驗證。在AuthenticationManager接口只有一個方法authenticate(…),而該方法的參數(shù)與返回類型均是Authentication。所以大多數(shù)過濾器在請求身份驗證前總是創(chuàng)建一個簡單的UsernamePasswordAuthenticationToken(該類是Authentication接口的子類)對象,將其作為AuthenticationManager.authenticate(…)方法中的參數(shù),再由AuthenticationProvider依據(jù)自身的特點創(chuàng)建相應(yīng)的Authentication接口子類的實例,因此身份驗證的具體信息也是在這最后一步完成的,即是在AuthenticationProvider中被創(chuàng)建與賦值的。其中就包括主體與憑證。如對于數(shù)據(jù)庫來說也是賬號與密碼。

    2) getAuthorities()得到當(dāng)前用戶所擁有的全部權(quán)限。Acegi提供一個GrantedAuthority接口,用于對應(yīng)應(yīng)用系統(tǒng)中有真正意義的權(quán)限實現(xiàn)。常用的是GrantedAuthorityImpl,它存儲主體的已獲授權(quán)的String表示,即權(quán)限也就是字符串的表示。而GrantedAuthority僅對字符做一層簡單的封裝。

    3) getDetails()獲取詳細(xì)資料,目的是得到當(dāng)前用戶的詳細(xì)信息,如在應(yīng)用系統(tǒng)可以是用戶的一個Bean(所在的部門,真實姓名…)。為此Acegi提供了一個UserDetails接口.

    l         isAccountNonExpired         帳號是否未過期

    l         isAccountNonLocked           帳號是否未鎖定

    l         isCredentialsNonExpired密碼是否未過期

    l         isEnabled                             是否可用(激活)

    我們會發(fā)現(xiàn)對于一個應(yīng)用系統(tǒng)來說,用戶的詳細(xì)信息中除與身份驗證相關(guān)的信息外還要很多其它的信息,如用戶所在的部門、電話。為此acegi提供了另一個接口AuthenticationDetailsSource,它僅提供一個方法buildDetails(HttpServletRequest request)用以創(chuàng)建客戶化的用戶信息。在過濾器中在執(zhí)行身份驗證之前調(diào)用該方法。

    4) isAuthenticated(),是否通過了身份驗證

    當(dāng)通過主體(帳號)從源(DAOCASJAAS…)中返回的信息中創(chuàng)建出Authentication實例后,還要校驗用戶的憑證(密碼)的一致性。對于提供了以PasswordEncoder接口為代表的一組密碼編碼器的實現(xiàn)

    4、 在我們討論對于身份驗證(Authentication)對象的保存之前,先來說明一下對它的訪問。為了確保任何對身份驗證感興趣的類型都可以訪問它,acegi通過SecurityContextHolder(該類中提供的所有成員方法均是靜態(tài)的)用來保持SecurityContextThreadLocal對象。

    通過SecurityContext類圖可以看出在它很簡單只是對Authentication對象的一個引用,之所以又做了這樣一層包裝的目的是為了客戶可以做任意的擴(kuò)展。由于SecurityContextHolder引用的是線程ThreadLocal集合,而對于B/S系統(tǒng)來說,一個線程的生命期還是太短了,無法保證SecurityContext對象的信息在一個線程執(zhí)行后不會被JVM垃圾回收。一般來說我們會將SecurityContext放到session中,但這樣又無法保證在邏輯層中訪問到session。對此acegi的解決方案是通過javax.servlet.Filter使不同與的訪問范圍與SecurityContextHolder做整合(session為例,每次請求過濾器都會從session中取得SecurityContext然后再將其賦到SecurityContextHolder)Acegi提供了多種整合過濾器,命名規(guī)則為*IntegrationFilter

    模塊

    功能

    HttpSessionContextIntegrationFilter

    請求之間使用HttpSession存儲SecurityContext

    HttpRequestIntegrationFilter

    HttpServletRequest.getUserPrincipal()獲得身份驗證,但在請求結(jié)束時不能將該身份驗證寫回該位置

    JbossIntegrationFilter

    Jbossjava:comp/env/security/subjectJNDI位置獲取身份驗證,但在請求結(jié)束時不能將該身份驗證寫回該位置

    接下來再來討論對Authentication的設(shè)置,當(dāng)處理過濾器調(diào)用AuthenticationManager. Authentication(…)獲得Authentication對象后,它會調(diào)用自身的成員方法successfulAuthentication(…)將其封裝為SecurityContext并設(shè)置到SecurityContextHolder中。

    注意successfulAuthentication(…)方法是在抽象類AbstractProcessingFilter中,而有一些處理過程器并沒有繼承該類,所以只有AbstractProcessingFilter的子類才會在當(dāng)前線程中取得SecurityContext對象。

    再來描述授權(quán)的后臺的處理過程

    1、 我們可能希望在三個地方做安全驗證,即是否可以訪問當(dāng)前頁面,是否可以調(diào)用當(dāng)前方法,是否可以控制當(dāng)前方法參數(shù)的對象域

    2、 對于安全驗證的判斷可能希望提供不同的表決策略,如一票否決制,還是有一票同意就通過或是同意大于否決票時才通過。

    3、 總之,所有需要的處理無非是在做這樣的工作。當(dāng)前用戶所擁有的權(quán)限中,否則有(或匹配)與當(dāng)前被調(diào)用者(頁面、方法、域)所指定的權(quán)限

    Acegi對于授權(quán)的技術(shù)實現(xiàn)

    從技術(shù)上話,授權(quán)完全與日志一樣是一個橫切關(guān)注點,與具體業(yè)務(wù)沒有任何關(guān)系。而Acegi只是借助SpringAOPjavax.servlet.Filter,對這授權(quán)方面的攔截。對于攔截器與其持有的對象Acegi提供如下實現(xiàn):

    攔截器

    描述

    持有的對象

    描述

    AbstractSecurityInterceptor

    是所有攔截器的抽象父類,實際授權(quán)的全部驗證過程均在該類beforeInvocation()afterInvocation()兩個方法中完成,子類只是區(qū)別不同類型的安全對象。

    FilterSecurityInterceptor

    是一個web的過濾器,用于對頁面(URL)的授權(quán)驗證

    FilterInvocation

    僅是對簡單crequestresponseFilterChain包裝的實現(xiàn)

    MethodSecurityInterceptor

    用于驗證Spring容器中bean的方法,并且需要使用Spring中的代理

    MethodInvocation

    AOP Alliance提供的被代理對象接口,運(yùn)行時的實際對象類型是由Spring提供的ReflectiveMethodInvocationCglibMethodInvocation

    AspectJSecurityInterceptor

    該類是在指定切入點調(diào)用AspectJ

    JoinPoint AspectJCallback

    執(zhí)行AspectJ的回調(diào)






    AbstractSecurityInterceptor的執(zhí)行過程:

    首先查詢應(yīng)用于該調(diào)用的配置屬性。如果沒有任何配置屬性,該調(diào)用被認(rèn)為是公有的,并且繼續(xù)進(jìn)行該調(diào)用。如果找到配置屬性,包含在SecurityContextHolder中的Authentication是通過AuthenticationManager驗證的,并且請求AccessDecisionManager來批準(zhǔn)該請求,如果成功RunAsManager可以替代該Authentication的標(biāo)識,然后繼續(xù)進(jìn)行該調(diào)用。調(diào)用完成時,將通過更新SecurityContextHolder來包含實際的身份驗證對象以清除RunAsManager的替代標(biāo)識。最后調(diào)用AfterInvocationManager,如果定義了的話。

    RunAsManager:該接口的主要作用成員方法是Authentication buildRunAs(Authentication authentication, Object object, ConfigAttributeDefinition config)目的是當(dāng)執(zhí)行特定操作時用于選擇性的替換Authentication對象,該方法是在安全驗證之后,安全對象執(zhí)行之前被調(diào)用。在安全對象執(zhí)行之后該方法對Authentication對象替換后被還原。

    AfterInvocationManager:作用是修改從安全對象調(diào)用中返回的對象。這通常被用來過濾僅針對已包含、已驗證元素的集合,或者如果信息是受保護(hù)的,轉(zhuǎn)換實例變量。如果該主體沒有針對返回對象的權(quán)限,它還可以拋出AccessDeniedException。主要的方法是

    Object decide(Authentication authentication, Object object, ConfigAttributeDefinition config,        Object returnedObject) throws AccessDeniedException,它需要返回一個對象,然后該對象將變成安全對象調(diào)用的結(jié)果。輪詢AfterInvocationProvider接口的具體類。

    最后分析權(quán)限表決的原理,還是讓我們虛擬這樣一個場景:

    1、 要求有兩個表決器,1)判斷當(dāng)前用戶是否為超級管理員,2)判斷當(dāng)前用戶是否擁有當(dāng)前所調(diào)用的方法或頁面的權(quán)限

    2、 如果其中任何一個表決器投出贊成票,就認(rèn)為通過。這是一種表決策略

    Acegi結(jié)合分析

    2、表決策略作用是輪詢所有的表決器,根據(jù)當(dāng)前策略結(jié)合表決器的表決結(jié)果,做出最終判斷結(jié)果。Acegi表決策略管理的接口是

    1)      decide(…)根據(jù)當(dāng)前用戶所擁有的權(quán)限信息[authentication],攔截器所持有的對象[object]以及在配置文件中所持有對象所必要的權(quán)限s[config],輪詢表決器做出決策。

    2)      supports(ConfigAttribute)判斷所有表決器是否有一個以上支持這種權(quán)限的表示形式

    3)      supports(Class) 判斷所有表決器是否有一個以上支持?jǐn)r截器所持有的對象類型

    后兩個方法主要在是各種攔截器初始化時調(diào)用,以但Spring驗證bean定義的合法性

    對于表決策略來說最終可能會得到三個結(jié)果中的一個贊成、否決或是棄權(quán)(結(jié)果是由表決器結(jié)合策略得到的)。對于棄權(quán)的產(chǎn)生是由于攔截器所持有的對象在配置中沒有設(shè)置任何權(quán)限。為此該接口的抽象子類提供allowIfAllAbstainDecisions開關(guān),如果所有表決器投出的均為棄權(quán)票,表示沒有通過授權(quán)則將該屬性設(shè)為true,默認(rèn)為false.

    Acegi提供了多種表決策略

    注意:一個表決器只能投一票

    AffirmativeBased       有一個決策器投出贊成票就通過

    ConsensusBased          贊成票大于否決票就通過,相同也算是沒有通過授權(quán)

    UnanimousBased        一票否決制,也就是只要有一個表決器投否決票就算不通過

    因此對于上面的場景我們應(yīng)該選擇AffirmativeBased表決策略,在決策略下還要有兩個表決器,下面介紹表決器

    1

    posted on 2011-03-31 19:07 張昊 閱讀(1982) 評論(1)  編輯  收藏

    Feedback

    # re: 通過場景分析acegi的設(shè)計原理 2011-03-31 23:07 popoer
    寫得不錯~  回復(fù)  更多評論
      


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 一个人看的www视频免费在线观看| 成人免费乱码大片A毛片| 国产一区二区免费在线| 9久久免费国产精品特黄| 亚洲综合久久久久久中文字幕| 搡女人真爽免费视频大全| 午夜在线免费视频 | 亚洲久本草在线中文字幕| 中文字幕无码免费久久99| 乱爱性全过程免费视频| 亚洲另类春色校园小说| 亚洲精品视频在线观看你懂的| 99re在线精品视频免费| 羞羞视频免费网站入口| 亚洲日韩中文字幕天堂不卡| 免费乱码中文字幕网站| 91高清免费国产自产拍2021| 欧洲亚洲综合一区二区三区| 久久久久亚洲精品日久生情| 四虎永久成人免费影院域名| a级特黄毛片免费观看| 亚洲人成色在线观看| 久久亚洲精品成人无码网站| 无码欧精品亚洲日韩一区夜夜嗨| 久久99国产综合精品免费| fc2成年免费共享视频网站| 狠狠色伊人亚洲综合网站色| 亚洲国产成人久久综合碰碰动漫3d| 日本a级片免费看| 免费不卡在线观看AV| 青青青视频免费观看| 在线精品亚洲一区二区| 亚洲视频一区网站| 国产AⅤ无码专区亚洲AV| 日韩激情无码免费毛片| 免费成人福利视频| 久久精品国产免费| 一级美国片免费看| 另类小说亚洲色图| 亚洲小说图区综合在线| 亚洲啪啪免费视频|