Acegi在appfuse中的應(yīng)用

          Posted on 2008-01-17 16:34 Boris 閱讀(243) 評(píng)論(0)  編輯  收藏
          Acegi是Spring Framework 下最成熟的安全系統(tǒng),它提供了強(qiáng)大靈活的企業(yè)級(jí)安全服務(wù),如完善的認(rèn)證和授權(quán)機(jī)制,Http資源訪問(wèn)控制,Method 調(diào)用訪問(wèn)控制,Access Control List (ACL) 基于對(duì)象實(shí)例的訪問(wèn)控制,Yale Central Authentication Service (CAS) 耶魯單點(diǎn)登陸,X509 認(rèn)證,當(dāng)前所有流行容器的認(rèn)證適配器,Channel Security頻道安全管理等功能。
          我著重說(shuō)明一下appfuse是怎么使用acegi的:
          1)web.xml:
          <filter>
          <filter-name>securityFilter</filter-name>
          <filter-class>org.acegisecurity.util.FilterToBeanProxy</filter-class>
          <init-param>
          <param-name>targetClass</param-name>
          <param-value>org.acegisecurity.util.FilterChainProxy</param-value>
          </init-param>
          </filter>
          

          Acegi通過(guò)實(shí)現(xiàn)了Filter接口的FilterToBeanProxy提供一種特殊的使用Servlet Filter的方式,它委托Spring中的Bean -- FilterChainProxy來(lái)完成過(guò)濾功能,這好處是簡(jiǎn)化了web.xml的配置,并且充分利用了Spring IOC的優(yōu)勢(shì)。FilterChainProxy包含了處理認(rèn)證過(guò)程的filter列表,每個(gè)filter都有各自的功能。
          <filter-mapping>限定了FilterToBeanProxy的URL匹配模式,有如下的請(qǐng)求才會(huì)受到權(quán)限控制。
          <filter-mapping>
          <filter-name>securityFilter</filter-name>
          <url-pattern>/j_security_check</url-pattern>
          </filter-mapping>
          <filter-mapping>
          <filter-name>securityFilter</filter-name>
          <url-pattern>/dwr/*</url-pattern>
          </filter-mapping>
          <filter-mapping>
          <filter-name>securityFilter</filter-name>
          <url-pattern>*.html</url-pattern>
          </filter-mapping>
          <filter-mapping>
          <filter-name>securityFilter</filter-name>
          <url-pattern>*.jsp</url-pattern>
          </filter-mapping>
          

          這里配置了其他的xml文件我們主要看/WEB-INF/security.xml。
          <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/applicationContext-*.xml,/WEB-INF/security.xml</param-value>
          </context-param>
          



          2)過(guò)濾的代理:
          在security中我們首先看到的是過(guò)濾代理:
          <!-- ======================== FILTER CHAIN ======================= -->
          <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
          <property name="filterInvocationDefinitionSource">
          <value>
          CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
          PATTERN_TYPE_APACHE_ANT
          /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
          </value>
          </property>
          </bean>
          

          其中CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON是 將請(qǐng)求轉(zhuǎn)變成為小寫(xiě)。
          PATTERN_TYPE_APACHE_ANT是按照ant的方式進(jìn)行匹配模式
          FilterChainProxy會(huì)按順序來(lái)調(diào)用這些filter,使這些filter能享用Spring ioc的功能。


          3)基本驗(yàn)證管理:
          我們先看一下它是怎么進(jìn)行驗(yàn)證管理的。
          <!-- 驗(yàn)證管理 -->
          <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
          <property name="providers">
          <list>
          <!-- 從數(shù)據(jù)庫(kù)中讀取用戶信息驗(yàn)證身份 -->
          <ref local="daoAuthenticationProvider"/>
          <!-- 匿名用戶身份認(rèn)證 -->
          <ref local="anonymousAuthenticationProvider"/>
          <!-- 已存cookie中的用戶信息身份認(rèn)證 -->
          <ref local="rememberMeAuthenticationProvider"/>
          </list>
          </property>
          </bean>
          <!-- 從數(shù)據(jù)庫(kù)中讀取用戶信息驗(yàn)證身份 -->
          <bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
          <property name="userDetailsService" ref="userDao"/>
          <property name="userCache" ref="userCache"/>
          <property name="passwordEncoder" ref="passwordEncoder"/>
          </bean>
          <!-- 匿名用戶身份認(rèn)證 -->
          <bean id="anonymousAuthenticationProvider" class="org.acegisecurity.providers.anonymous.AnonymousAuthenticationProvider">
          <property name="key" value="anonymous"/>
          </bean>
          <!-- 已存cookie中的用戶信息身份認(rèn)證 -->
          <bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
          <property name="key" value="appfuseRocks"/>
          </bean>
          

          首先daoAuthenticationProvider是從數(shù)據(jù)庫(kù)中讀取數(shù)據(jù)進(jìn)行驗(yàn)證。
          userDetailsService屬性使用了userDao進(jìn)行的讀取(userDao實(shí)現(xiàn)org.acegisecurity.userdetails.UserDetailsService接口,而user類實(shí)現(xiàn)org.acegisecurity.userdetails.UserDetails才能userDetailsService里使用),還可以使用其他的方式比如直接鏈接數(shù)據(jù)源等等。
          userCache屬性注明使用緩存,對(duì)于不經(jīng)常改變的user放到緩存里可以大大減少數(shù)據(jù)庫(kù)的負(fù)擔(dān)。也可以選擇不使用,如果不使用則每次都登錄都從數(shù)據(jù)中查詢用戶信息。
          passwordEncoder屬性則注明密碼加密的方法,
          使用加密器對(duì)用戶輸入的明文進(jìn)行加密。Acegi提供了三種加密器:
          PlaintextPasswordEncoder—默認(rèn),不加密,返回明文.
          ShaPasswordEncoder—哈希算法(SHA)加密
          Md5PasswordEncoder—消息摘要(MD5)加密
          <bean id="passwordEncoder" class="org.acegisecurity.providers.encoding.ShaPasswordEncoder"/>
          

          這里使用的哈希算法(SHA)加密。
          其次,anonymousAuthenticationProvider是給與匿名用戶一個(gè)匿名的權(quán)限anonymous。
          最后,rememberMeAuthenticationProvider則是把登錄的權(quán)限存儲(chǔ)在cookie里,不loginout時(shí)關(guān)閉瀏覽器,再度打開(kāi)瀏覽器依舊保留權(quán)限(密碼修改時(shí)有特殊的限制)。
          驗(yàn)證管理者(authenticationManager)包含三個(gè)驗(yàn)證提供者(daoAuthenticationProvider, anonymousAuthenticationProvider,rememberMeAuthenticationProvider),當(dāng)然可以適當(dāng)?shù)暮?jiǎn)略。


          怎么進(jìn)行驗(yàn)證的呢?
          3)過(guò)濾:

          1.HttpSessionContextIntegrationFilter
          每次request前 HttpSessionContextIntegrationFilter從Session中獲取Authentication對(duì)象,在request完后, 又把Authentication對(duì)象保存到Session中供下次request使用,此filter必須其他Acegi filter前使用,使之能跨越多個(gè)請(qǐng)求。

          2. logoutFilter
          該Filter負(fù)責(zé)處理退出登錄后所需要的清理工作。它會(huì)把session銷(xiāo)毀,把ContextHolder清空, 把rememberMeServices從cookies中清除掉,然后重定向到指定的退出登陸頁(yè)面。

          3. authenticationProcessingFilter
          該Filter負(fù)責(zé)處理登陸身份驗(yàn)證。當(dāng)接受到與filterProcessesUrl所定義相同的請(qǐng)求時(shí),它會(huì)首先通過(guò)AuthenticationManager來(lái)驗(yàn)證用戶身份。如果驗(yàn)證成功,則重定向到defaultTargetUrl所定義的成功登陸頁(yè)面。如果驗(yàn)證失敗,則再?gòu)膔ememberMeServices中獲取用戶身份,若再獲取失敗,則重定向到authenticationFailureUrl所定義登陸失敗頁(yè)面。
          配置如下:
          <bean id="authenticationProcessingFilter" class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
          <property name="authenticationManager" ref="authenticationManager"/>
          <property name="authenticationFailureUrl" value="/login.jsp?error=true"/>
          <property name="defaultTargetUrl" value="/"/>
          <property name="filterProcessesUrl" value="/j_security_check"/>
          <property name="rememberMeServices" ref="rememberMeServices"/>
          </bean>
          

          authenticationFailureUrl定義登陸失敗時(shí)轉(zhuǎn)向的頁(yè)面
          defaultTargetUrl定義登陸成功時(shí)轉(zhuǎn)向的頁(yè)面
          filterProcessesUrl定義登陸請(qǐng)求的頁(yè)面
          rememberMeServices用于在驗(yàn)證成功后添加cookie信息

          4.securityContextHolderAwareRequestFilter
          該Filter負(fù)責(zé)通過(guò)Decorate Model(裝飾模式),裝飾的HttpServletRequest對(duì)象。其Wapper是ServletRequest包裝類HttpServletRequestWrapper的子類(SavedRequestAwareWrapper或SecurityContextHolderAwareRequestWrapper),附上獲取用戶權(quán)限信息,request參數(shù),headers, Date headers 和 cookies 的方法。
          p.s. 如果把channelProcessingFilter放到securityContextHolderAwareRequestFilter前面則進(jìn)行SSL的過(guò)濾。

          5.rememberMeProcessingFilter
          該Filter負(fù)責(zé)在用戶登錄后在本地機(jī)上記錄用戶cookies信息,免除下次再次登陸。檢查AuthenticationManager 中是否已存在Authentication對(duì)象,如果不存在則會(huì)調(diào)用RememberMeServices的aotoLogin方法來(lái)從cookies中獲取Authentication對(duì)象

          6.anonymousProcessingFilter
          該Filter負(fù)責(zé)為當(dāng)不存在任何授權(quán)信息時(shí),自動(dòng)為Authentication對(duì)象添加userAttribute中定義的匿名用戶權(quán)限

          7.exceptionTranslationFilter
          該過(guò)濾器負(fù)責(zé)處理各種異常,然后重定向到相應(yīng)的頁(yè)面中。

          8.filterInvocationInterceptor
          該過(guò)濾器會(huì)首先調(diào)用AuthenticationManager判斷用戶是否已登陸認(rèn)證,如還沒(méi)認(rèn)證成功,則重定向到登陸界面。認(rèn)證成功,則并從Authentication中獲取用戶的權(quán)限。然后從objectDefinitionSource屬性獲取各種URL資源所對(duì)應(yīng)的權(quán)限。最后調(diào)用AccessDecisionManager來(lái)判斷用戶所擁有的權(quán)限與當(dāng)前受保華的URL資源所對(duì)應(yīng)的權(quán)限是否相匹配。如果匹配失敗,則返回403錯(cuò)誤(禁止訪問(wèn))給用戶。匹配成功則用戶可以訪問(wèn)受保護(hù)的URL資源。
          <bean id="filterInvocationInterceptor" class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
          <property name="authenticationManager" ref="authenticationManager"/>
          <property name="accessDecisionManager" ref="accessDecisionManager"/>
          <property name="objectDefinitionSource">
          <value>
          PATTERN_TYPE_APACHE_ANT
          /clickstreams.jsp*=admin
          /flushCache.*=admin
          /passwordHint.html*=ROLE_ANONYMOUS,admin,user
          /reload.*=admin
          /signup.html*=ROLE_ANONYMOUS,admin,user
          /users.html*=admin
          /**/*.html*=admin,user
          </value>
          </property>
          </bean>
          

          其中使用了accessDecisionManager,他是經(jīng)過(guò)投票機(jī)制來(lái)決定是否可以訪問(wèn)某一資源(URL或方法)。allowIfAllAbstainDecisions為false時(shí)如果有一個(gè)或以上的decisionVoters投票通過(guò),則授權(quán)通過(guò)。可選的決策機(jī)制有ConsensusBased和UnanimousBased。
          <bean id="accessDecisionManager" class="org.acegisecurity.vote.AffirmativeBased">
          <property name="allowIfAllAbstainDecisions" value="false"/>
          <property name="decisionVoters">
          <list>
          <bean class="org.acegisecurity.vote.RoleVoter">
          <property name="rolePrefix" value=""/>
          </bean>
          </list>
          </property>
          </bean>
          

          roleVoter表示必須是以rolePrefix設(shè)定的value開(kāi)頭的權(quán)限才能進(jìn)行投票,如AUTH_ , ROLE_等,實(shí)現(xiàn)用戶分組。
          4)方法執(zhí)行前權(quán)限驗(yàn)證
          <!-- 類代理 -->
          <aop:config>
          <aop:advisor id="managerSecurity" advice-ref="methodSecurityInterceptor" pointcut="execution(* cn.scs.service.UserManager.*(..))"/>
          <aop:advisor id="personManagerSecurity" advice-ref="methodSecurityInterceptor" pointcut="execution(* cn.scs.service.PersonManager.*(..))"/>
          </aop:config>
          <!-- 在執(zhí)行方法前進(jìn)行攔截,檢查用戶權(quán)限信息 -->
          <bean id="methodSecurityInterceptor" class="org.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
          <property name="authenticationManager" ref="authenticationManager"/>
          <property name="accessDecisionManager" ref="accessDecisionManager"/>
          <property name="objectDefinitionSource">
          <value>
          cn.scs.service.UserManager.getUsers=admin
          cn.scs.service.UserManager.removeUser=admin
          cn.scs.service.PersonManager.getPeople=ROLE_ANONYMOUS
          </value>
          </property>
          </bean>
          

          可以把類MethodSecurityInterceptor注入到代理了的類中,實(shí)現(xiàn)在方法執(zhí)行之前進(jìn)行驗(yàn)證。
          aecgi的常用標(biāo)簽(一共只有4個(gè))
          <authz:authorize>
          

          這個(gè)標(biāo)簽來(lái)控制頁(yè)面元素的顯示與否。
          主要有如下屬性
          ifAnyGranted 只要有任意權(quán)限相當(dāng)于或者(||)這個(gè)經(jīng)常使用
          ifAllGranted 需要有所列出的全部權(quán)限 相當(dāng)于并且(&&)
          ifNotGranted 不能有任意權(quán)限 相當(dāng)于非(!)和第一個(gè)配合使用
          用這些就可以控制頁(yè)面元素的顯示與否了
          例:
          <authz:authorize ifAnyGranted="ROLE_ADMIN">
          <display:column property="infoId" sortable="true" href="infoContentform.html?typeId=${typeId}" media="html"
          paramId="infoId" paramProperty="infoId" titleKey="infoContent.infoId"/>
          </authz:authorize>
          <authz:authorize ifNotGranted="ROLE_ADMIN">
          <display:column property="infoId" sortable="true" titleKey="infoContent.infoId"/>
          </authz:authorize>
          

          結(jié)合了<authz:authorize>控制displayTag標(biāo)簽的顯示。

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


          網(wǎng)站導(dǎo)航:
           

          posts - 1, comments - 0, trackbacks - 0, articles - 2

          Copyright © Boris

          主站蜘蛛池模板: 阿克苏市| 广饶县| 西丰县| 筠连县| 佛学| 南开区| 白沙| 同仁县| 泾川县| 新野县| 博客| 云龙县| 稷山县| 定安县| 伽师县| 桐乡市| 儋州市| 天水市| 惠东县| 田阳县| 无极县| 泊头市| 衢州市| 南澳县| 方城县| 开封县| 丰县| 彩票| 申扎县| 河源市| 全南县| 远安县| 三门峡市| 永济市| 定州市| 安陆市| 会东县| 公主岭市| 昌吉市| 手游| 南靖县|