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=1</value></property>
<property name="defaultTargetUrl"><value>/</value></property>
<property name="filterProcessesUrl"><value>/j_acegi_security_check</value></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 Realm</value></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>false</value>
</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>false</value>
</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>userCache</value>
</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>foobar</value></property>
</bean>
rememberMeAuthenticationProvider負責Cookies記憶用戶RememberMeAuthenticationToken的進一步處理
<bean id="rememberMeAuthenticationProvider" class="org.acegisecurity.providers.rememberme.RememberMeAuthenticationProvider">
<property name="key"><value>springRocks</value></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_password</value>
</property>
</bean>
posted on 2007-11-20 11:08
扭曲的鉛筆 閱讀(475)
評論(1) 編輯 收藏 所屬分類:
Spring