Acegi 设计概述
作者: cac,作者保留版权,转载请注明出处。
http://wiki.springside.org.cn/display/springside/AcegiGeneralDesign
第一步, 认证(authentication)。Acegi调用AuthenticationManager(认证管理器)来对当前请求登陆系统用户进行验证,AuthenticationManager负责委托一个或多个Provider(认证提供者),并逐一遍历每个Provider,直到某一个Provider能够成功的验证用户的身份。Provider成功验证用户身份后,会返回一个Authentication(证明), Authentication中包括Principal(用户名),Credentials(通常是密码),Authorities(该用户所拥有的权限)。这样就完成了身份验证的步骤。
第二步,授权(authorization)。当Acegi获得Authentication后,也就确定了用户的身份。每当用户请求访问某受保护资源时,Acegi会调用AccessDecisionManager(访问决策管理器)来决定用户的Authentication是否有恰当的权限来访问当前访问的受保护资源,有则授权用户通过,无则抛出错误信息,以达到访问控制的目的。
Acegi的FilterChainProxy提供了一种很好的方式,使你不需要在web.xml配置Filters,而在Spring配置文件中加入, 从而能充分利用Spring IOC的优势。
FilterChainProxy其实也只是一个扩展后的Filter,它负责委托Spring中的各个实现了javax.servlet.Filter接口的Bean来执行过滤功能。 如httpSessionContextIntegrationFilter, authenticationProcessingFilter, filterInvocationInterceptor等。
在web.xml中的配置FilterToBeanProxy:
<filter>
<filter-name>Acegi Filter Chain Proxy</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>
<filter-mapping>
<filter-name>Acegi Filter Chain Proxy</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在Spring配置文件中相应的FilterChainProxy Bean:
<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>
Acegi的异常管理机制做得不错,基本上可以满足权限管理需求。在其结构基础上继承实现自己的异常类也是很方便的。
所有Acegi的异常都是在 AcegiSecurityException 上继承而来的,其中最主要的是 AuthenticationException 和 AccessDeniedException。
这里需要注意的是 AcegiSecurityException 继承了Spring的 NestedRuntimeException,而NestedRuntimeException又是继承RuntimeException的。
所以抛出的时候不需要throws, 而捕捉的时候需要专门catch RuntimeException。
AuthenticationException 是所有授权相关的异常的父类,当用户身份验证失败时就会抛出这个异常。
AccessDeniedException 是所有认证相关的异常的父类,当资源被拒绝访问时就会抛出这个异常。
在Acegi 中,通过ExceptionTranslationFilter(异常转换过滤器)来对各种异常进行捕获和处理,并重定向到不同的错误信息显示页面。
如遇到AuthenticationException 就会重定向到登陆页面,遇到AccessDeniedException 就会无权访问资源页面。你还可以继承ExceptionTranslationFilter基础上覆盖handleException方法来实现你自己的系统中异常的处理。
<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>