入門Acegi最重要的是了解基本架構,如此就不會被一堆設定檔案搞的混頭轉向,從先前“第一個Acegi程式”,可以看到Acegi系統包括的四個主要類型元件:Filter、Manager、Provider與Handler。
當一個請求到來時,在安全處理上最高層的元件,像是會話處理、驗證、登出等,并呼叫對應的物件進行處理。
真正處理驗證、登出等安全服務之元件,Manager管理Provider所提供的安全相關資訊。
提供安全相關資訊給Manager,安全資訊來源可能是記憶體中的物件、檔案、資料庫等儲存媒介,安全資訊包括了使用者名稱、密碼、角色等訊息。
有時會將一個安全服務分作數個小任務來進行,每個小任務由一個Handler來進行處理,如此在處理安全服務或設定Acegi時可以更有彈性,例如依需求處理登出時Session的失效與Cookie的失效。
Acegi使用Filter來對請求進行驗證與授權等安全服務:
<!-- 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,authenticationProcessingFilter,
exceptionTranslationFilter,filterSecurityInterceptor
</value>
</property>
</bean>
以下介紹主要的幾個Filter:
- Session Integration Filter
通常是Filter Chain中第一個Filter,會建立Security
Context 物件用以儲存安全相關資訊,后續的Filter若有需要儲存或取得安全相關資訊,即可利用Security Context
物件,如果Security Context物件中的資訊有所變動,Session Integration
Filter會將變動儲存至Session物件之中,否則將Security
Context物件棄置,例如“第一個Acegi程式”中所使用的Authentication Processing
Filter,即利用Security Context物件來儲存使用者名稱、密碼等使用者資訊。
- Authentication Processing Filter
當使用者存取受保護資源而需要登入時,Authentication
Processing Filter可提供表單來源給使用者,之后從使用者的請求(物件)中取得名稱、密碼并建立authentication
token以儲存資訊,接著將之交給驗證管理員(authentication
manager)進行以進行使用者的比對,所以基本上,Authentication Processing Filter需要設定以下的資訊:
<!-- 驗證處理,使用表單 -->
<bean id="authenticationProcessingFilter"
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
<!-- 驗證管理員,處理驗證資訊提供者 -->
<property name="authenticationManager" ref="authenticationManager"/>
<!-- 驗證失敗URL -->
<property name="authenticationFailureUrl" value="/acegilogin.jsp"/>
<!-- 驗證成功預設URL -->
<property name="defaultTargetUrl" value="/protected/userinfo.jsp"/>
<!-- 驗證處理的提交位址 -->
<property name="filterProcessesUrl" value="/j_acegi_security_check"/>
</bean>
當驗證管理員進行使用者的比對、取得細節資訊并返回Authentication
Processing Filter后,Authentication Processing
Filter會建立Authentication并將取得的使用者資訊儲存在Security
Context物件中,然后交給下一個Filter繼續進行處理。
- Exception Translation Filter
當驗證或授權過程中發生例外時,Exception Translation Filter處理例外。
<!-- 發生驗證錯誤或權限錯誤時的處理 -->
<bean id="exceptionTranslationFilter" class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint">
<bean
class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<property name="loginFormUrl" value="/acegilogin.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>
<!-- 登出處理 -->
<bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
<constructor-arg value="/acegilogin.jsp"/> <!-- 登出后的顯示頁面 -->
<constructor-arg>
<list>
<bean
class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
</list>
</constructor-arg>
</bean>
用來決定是否授權,驗證與授權是一體的,所以在Authentication
Processing Filter之后必須設定Interceptor filters,Interceptor
filters使用您所設定的存取控制策略(access control
policy)來決定是否授權,一個使用者的存取控制策略定義了使用者、密碼、角色等資訊:
caterpillar=123456,ROLE_SUPERVISOR
您使用Interceptor filters來進行存取控制策略的設定,設定驗證管理者與存取決策理員(Access Decision Manager),受保護的資源可存取之角色,存取決策管理員會以投票方式決定資源是否授權,例如:
<!-- FilterSecurityInterceptor 對 URI 進行保護 -->
<bean id="filterSecurityInterceptor"
class="org.acegisecurity.intercept.web.FilterSecurityInterceptor">
<!-- 驗證管理員 -->
<property name="authenticationManager" ref="authenticationManager" />
<!-- 授權管理員 -->
<property name="accessDecisionManager" ref="accessDecisionManager" />
<property name="objectDefinitionSource">
<value>
CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
PATTERN_TYPE_APACHE_ANT
/protected/**=ROLE_SUPERVISOR,ROLE_USER
</value>
</property>
</bean>