Aceg應用

1.Filter 組件

HttpSessionContextIntegrationFilter

該Filter負責每次請求前從HttpSession中獲取Authentication對象,然後把Authentication存於一個新的 ContextHolder對象(其實質上只是一個ThreadLocal對象)中,則讓該次請求過程中的任何Filter都可以通過 ContextHolder來共享Authentication,而不需要從HttpSession中取,減少傳HttpRequest參數的麻煩。在請 求完後把Authentication對象保存到HttpSession中供下次請求使用, 最後把剛纔生成的ContextHolder對象銷燬。這樣就達到了讓Authentication對象跨越多個請求的目的。

注意此filter須在調用其他Acegi filter前使用:

<bean id="httpSessionContextIntegrationFilter" class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
bean>

    AuthenticationProcessingFilter

該Filter負責處理登陸身份驗證。當接受到與filterProcessesUrl所定義相同的請求時,它會首先通過 AuthenticationManager來驗證用戶身份。如果驗證成功,則重定向到defaultTargetUrl所定義的成功登陸頁面。如果驗證 失敗,則再從rememberMeServices中獲取用戶身份,若再獲取失敗,則重定向到authenticationFailureUrl所定義登 陸失敗頁面。

<bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
      <property name="authenticationManager"><ref bean="authenticationManager"/>property>
      <property name="authenticationFailureUrl"><value>/acegilogin.jsp?login_error=1value>property>
      <property name="defaultTargetUrl"><value>/value>property>
      <property name="filterProcessesUrl"><value>/j_acegi_security_checkvalue>property>
      <property name="rememberMeServices"><ref local="rememberMeServices"/>property>
bean>

    LogoutFilter

該Filter負責處理退出登錄後所需要的清理工作。它會把session銷燬,把ContextHolder清空, 把rememberMeServices從cookies中清除掉,然後重定向到指定的退出登陸頁面。

<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
      <constructor-arg value="/index.jsp"/> -- URL redirected to after logout ->
      <constructor-arg>
         <list>
              <ref bean="rememberMeServices"/>
              <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
         list>
      constructor-arg>
bean>

    FilterInvocationInterceptor

該過濾器會首先調用AuthenticationManager判斷用戶是否已登陸認證,如還沒認證成功,則重定向到登陸界面。認證成功,則並從 Authentication中獲取用戶的權限。然後從objectDefinitionSource屬性獲取各種URL資源所對應的權限。最後調用 AccessDecisionManager來判斷用戶所擁有的權限與當前受保華的URL資源所對應的權限是否相匹配。如果匹配失敗,則返回403錯誤 (禁止訪問)給用戶。匹配成功則用戶可以訪問受保護的URL資源。

<bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
      <property name="authenticationManager"><ref bean="authenticationManager"/>property>
      <property name="accessDecisionManager"><ref local="httpRequestAccessDecisionManager"/>property>
      <property name="objectDefinitionSource">
         <value>
                                CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
                                PATTERN_TYPE_APACHE_ANT
                                /index.jsp=ROLE_ANONYMOUS,ROLE_USER
                                /hello.htm=ROLE_ANONYMOUS,ROLE_USER
                                /logoff.jsp=ROLE_ANONYMOUS,ROLE_USER
                                /switchuser.jsp=ROLE_SUPERVISOR
                                /j_acegi_switch_user=ROLE_SUPERVISOR
                                /acegilogin.jsp*=ROLE_ANONYMOUS,ROLE_USER
                                /**=ROLE_USER
        value>
      property>
bean>

    SecurityContextHolderAwareRequestFilter

該Filter負責通過Decorate Model(裝飾模式),裝飾的HttpServletRequest對象。其Wapper是ServletRequest包裝類 HttpServletRequestWrapper的子類(SavedRequestAwareWrapper或 SecurityContextHolderAwareRequestWrapper),附上獲取用戶權限信息,request參數,headers, Date headers 和 cookies 的方法。

<bean id="securityContextHolderAwareRequestFilter" class="org.acegisecurity.wrapper.SecurityContextHolderAwareRequestFilter" />

    BasicProcessingFilter

該Filter負責處理HTTP頭的認證信息,如從Spring遠程協議(如Hessian和Burlap)或普通的瀏覽器如IE, Navigator的HTTP頭中獲取用戶信息,將他們轉交給通過authenticationManager屬性裝配的認證管理器。如果認證成功,會將 一個Authentication對象放到會話中,否則,如果認證失敗,會將控制轉交給認證入口點(通過 authenticationEntryPoint屬性裝配)

   <bean id="basicProcessingFilter" class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">
      <property name="authenticationManager"><ref local="authenticationManager"/>property>
      <property name="authenticationEntryPoint"><ref local="basicProcessingFilterEntryPoint"/>property>
   bean>

   <bean id="basicProcessingFilterEntryPoint" class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
      <property name="realmName"><value>Contacts Realmvalue>property>
   bean>

    RememberMeProcessingFilter

該Filter負責在用戶登錄後在本地機上記錄用戶cookies信息,免除下次再次登陸。檢查AuthenticationManager 中是否已存在Authentication對象,如果不存在則會調用RememberMeServices的aotoLogin方法來從cookies中 獲取Authentication對象

    <bean id="rememberMeProcessingFilter" class="org.acegisecurity.ui.rememberme.RememberMeProcessingFilter">
                   <property name="authenticationManager" ref="authenticationManager" />
                   <property name="rememberMeServices" ref="rememberMeServices" />
    bean>

    AnonymousProcessingFilter

該Filter負責爲當不存在任何授權信息時,自動爲Authentication對象添加userAttribute中定義的匿名用戶權限

    <bean id="anonymousProcessingFilter" class="org.acegisecurity.providers.anonymous.AnonymousProcessingFilter">
         <property name="key" value="changeThis" />
         <property name="userAttribute" value="anonymousUser,ROLE_ANONYMOUS" />
    bean>

    ExceptionTranslationFilter

該過濾器負責處理各種異常,然後重定向到相應的頁面中。

         <bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
                   <property name="authenticationEntryPoint">
                            <bean class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
                                     <property name="loginFormUrl" value="/login.jsp" />
                                     <property name="forceHttps" value="false" />
                            bean>
                   property>
                   <property name="accessDeniedHandler">
                            <bean class="org.acegisecurity.ui.AccessDeniedHandlerImpl">
                                     <property name="errorPage" value="/accessDenied.jsp" />
                            bean>
                   property>
         bean>

2. 攔截器組件

    MethodSecurityInterceptor

該攔截器實現了org.aopalliance.intercept.MethodInterceptor接口。在方法被調用之前,攔截器會先調用 AuthenticationManager判斷用戶身份是否已驗證,然後從objectDefinitionSource中獲取方法所對應的權限,再調 用AccessDecisionManager來匹配用戶權限和方法對應的權限。如果用戶沒有足夠權限調用當前方法,則拋出 AccessDeniedException使方法不能被調用。調用runAsManager,使在調用方法前動態改變Authentication中獲 取用戶權限。

    <bean id="securityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
                   <property name="validateConfigAttributes">
                            <value>falsevalue>
                   property>
                  <property name="authenticationManager">
                            <ref local="authenticationManager" />
                   property>
                   <property name="accessDecisionManager">
                            <ref local="accessDecisionManager" />
                   property>
                   <property name="runAsManager">
                            <ref local="runAsManager" />
                   property>
                   <property name="objectDefinitionSource">
                       <value>
                         sample.contact.ContactManager.create=ROLE_USER
                         sample.contact.ContactManager.getAllRecipients=ROLE_ADMIN
                       value>
                   property>
     bean>

    BeanNameAutoProxyCreator

設置AOP代理的最簡單方法就是用Spring的BeanNameAutoProxyCreator。在BeanNameAutoProxyCreator中選出你所需要的interceptor, 和列出你所需要保護的Bean。

    <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
                   <property name="proxyTargetClass" value="true" />
                   <property name="interceptorNames">
                            <list>
                                     <idref local="securityInterceptor" />
                            list>
                   property>
                   <property name="beanNames">
                            <list>
                                <idref bean="userManager"/>
                                <idref bean="roleManager"/>
                                <idref bean="rescManager"/>
                            list>
                   property>
     bean>

3. 其它組件

    AccessDecisionManager

AccessDecisionManager接口有decide()和support()方法。decide()方法是進行決策是否批准通過,如果 沒拋出AccessDeniedException則爲允許訪問資源,否則拒絕訪問。support()方法是根據配置屬性和受保護資源的類來判斷是否需 要對該資源作出決策判斷。

AccessDecisionManager的 decisionVoters屬性需要一個或多個Voter(投票者),Voter必須實現AccessDecisionVoter 接口。Voter的工作是去匹配用戶已擁有的權限和受保護的資源要求的權限,在該資源有相應權限的情況下,如果匹配則投允許票,否則投反對票。 allowIfAllAbstainDecisions屬性表示是否允許所有都棄權時就通過。Voter的實現類RoleVoter在當受保護資源的名字 由ROLE_開始時才參與投票。

AccessDecisionManager有三個實現類,功能各不相同:
AffirmativeBased: 當至少有一個Voter投允許票時才通過
UnanimousBased: 沒有Voter投反對票時才通過
ConsensusBased: 當所有Voter都投允許票時才通過

<bean id="accessDecisionManager" class="org.acegisecurity.vote.UnanimousBased">
        <property name="allowIfAllAbstainDecisions">
                <value>falsevalue>
        property>
        <property name="decisionVoters">
                <list>
                        <ref local="roleVoter" />
                list>
        property>
 bean>

<bean id="roleVoter" class="org.acegisecurity.vote.RoleVoter" />

    AuthenticationManager

AuthenticationManager的其中一個實現是ProviderManager,它負責把身份驗證的工作委託給一個或多個Provider(認證提供者)。

Provider都是實現AuthenticationProvider接口,該接口有兩個方法authenticate()和support ()。authenticate()方法會嘗試驗證用戶身份,若驗證成功則返回一個Authentication對象,否則拋出一個 AuthenticationException。

support()方法會評估當前Authentication對象是否適合這Provider來進行進一步的處理,而不是指已經通過。

Provir有多個實現, 例如daoAuthenticationProvider,anonymousAuthenticationProvider,rememberMeAuthenticationProvider。

<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
      <property name="providers">
         <list>
            <ref local="daoAuthenticationProvider"/>
            <ref local="anonymousAuthenticationProvider"/>
             <ref local="rememberMeAuthenticationProvider"/>
         list>
      property>
bean>

daoAuthenticationProvider負責提供用戶信息,包括用戶名和密碼。其中取用戶名密碼的工作就交給 userDetailsService來做。通過userCache來緩存用戶信息,減少查詢數據庫次數。用passwordEncoder來使用加密密 碼。userDetailsService的接口實現有jdbcDaoImpl和inMemoryDaoImpl。jdbcDaoImpl通過數據庫獲取 用戶名和密碼,而inMemoryDaoImpl則只是通過xml定義的方式來獲取。
userCache的接口實現有EhCacheBasedUserCache和NullUserCache。NullUserCache實際上就是不進行緩存。EhCacheBasedUserCache是基於ehcache的開源緩存項目來實現的。
passwordEncoder是使用加密器對用戶輸入的明文進行加密。Acegi提供了三種加密器:
PlaintextPasswordEncoder---默認,不加密,返回明文.
ShaPasswordEncoder---哈希算法(SHA)加密
d5PasswordEncoder---消息摘要(MD5)加密

<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
      <property name="userDetailsService"><ref local="jdbcDaoImpl"/>property>
      <property name="userCache"><ref local="userCache"/>property>
      <property name="passwordEncoder"><ref local="passwordEncoder"/>property>
bean>

<bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
      <property name="dataSource"><ref bean="dataSource"/>property>
bean>

<bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache">
      <property name="cache"><ref local="userCacheBackend"/>property>
bean>

<bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.Md5PasswordEncoder"/>

<bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
      <property name="cacheManager">
         <ref local="cacheManager"/>
      property>
      <property name="cacheName">
         <value>userCachevalue>
      property>
bean>

<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>

anonymousAuthenticationProvider負責匿名用戶的AnonymousAuthenticationToken的進一步處理

<bean id="anonymousAuthenticationProvider" class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
      <property name="key"><value>foobarvalue>property>
bean>

rememberMeAuthenticationProvider負責Cookies記憶用戶RememberMeAuthenticationToken的進一步處理

<bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
      <property name="key"><value>springRocksvalue>property>
bean>

    RememberMeServices

rememberMeServices負責通過以cookie的形式保存先前的用戶登錄信息。在Authentication對象不存在時, rememberMeProcessingFilter會調用rememberMeServices的autoLogin()方法,嘗試在cookie中 獲取用戶登錄信息,如果存在則並返回Authentication對象。在每次用戶登錄時,如果設置了RememberMe功能,在驗證用戶身份成功後, 則會調用loginSuccess()方法記錄用戶信息在cookie中,否則調用loginFail()方法清除cookie。

<bean id="rememberMeServices" class="org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices">
        <property name="userDetailsService" ref="userDetailsService" />
        <property name="key" value="changeThis" />
bean>

    runAsManager

runAsManager提供了動態替換 ContextHolder中Authentication對象的功能。

<bean id="runAsManager" class="org.acegisecurity.runas.RunAsManagerImpl">
        <property name="key">
                <value>my_run_as_passwordvalue>
        property>
bean>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章