入门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>