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