<script type="text/javascript"> </script>
先来谈一谈 Acegi 的基础知识, Acegi 的架构比较复杂,但是我希望我下面的只言片语能够把它说清楚。大家都知道,如果要对 Web 资源进行保护,最好的办法莫过于 Filter ,要想对方法调用进行保护,最好的办法莫过于 AOP 。 Acegi 对 Web 资源的保护,就是靠 Filter 实现的。如下图:
一般来说,我们的 Filter 都是配置在 web.xml 中,但是 Acegi 不一样,它在 web.xml 中配置的只是一个代理,而真正起作用的 Filter 是作为 Bean 配置在 Spring 中的。 web.xml 中的代理依次调用这些 Bean ,就实现了对 Web 资源的保护,同时这些 Filter 作为 Bean 被 Spring 管理,所以实现 AOP 也很简单,真的是一举两得啊。
Acegi 中提供的 Filter 不少,有十多个,一个一个学起来比较复杂。但是对于我们 Web 开发者来说,常用的就那么几个,如下图中的被红圈圈标记出来的:
从上到下,它们实现的功能依次是 1 、制定必须为 https 连接; 2 、从 Session 中提取用户的认证信息; 3 、退出登录; 4 、登录; 5 、记住用户; 6 、所有的应用必须配置这个 Filter 。
一般来说,我们写 Web 应用只需要熟悉这几个 Filter 就可以了,如果不需要 https 连接,连第一个也不用熟悉。但是有人肯定会想,这些 Filter 怎么和我的数据库联系起来呢?不用着急,这些 Filter 并不直接处理用户的认证,也不直接处理用户的授权,而是把它们交给了认证管理器和决策管理器。如下图:
对于这两种管理器,那也是不需要我们写代码的, Acegi 也提供了现成的类。那么大家又奇怪了:又是现成的,那怎么和我的数据库关联起来呢?别着急,其实这两个管理器自己也不做事,认证管理器把任务交给了 Provider ,而决策管理器则把任务交给了 Voter ,如下图:
现在我要告诉你们,这里的 Provider 和 Voter 也是不需要我们写代码的。不要崩溃,快到目标了。 Acegi 提供了多个 Provider 的实现类,如果我们想用数据库来储存用户的认证数据,那么我们就选择 DaoAuthenticationProvider 。对于 Voter ,我们一般选择 RoleVoter 就够用了,它会根据我们配置文件中的设置来决定是否允许某一个用户访问制定的 Web 资源。
而 DaoAuthenticationProvider 也是不直接操作数据库的,它把任务委托给了 UserDetailService ,如下图:
插入一些相关教程
2) httpSessionContextIntegrationFilter
每次request前 HttpSessionContextIntegrationFilter从Session中获取Authentication对象,在request完后, 又把Authentication对象保存到Session中供下次request使用,此filter必须其他Acegi filter前使用,使之能跨越多个请求。
<bean id="httpSessionContextIntegrationFilter"
class="org.acegisecurity.context.HttpSessionContextIntegrationFilter">
</bean>
3) basicProcessingFilter
用于处理HTTP头的认证信息,如从Spring远程协议(如Hessian和Burlap)或普通的浏览器如IE,Navigator的HTTP头中获取用户信息,将他们转交给通过authenticationManager属性装配的认证管理器。如果认证成功,会将一个Authentication对象放到会话中,否则,如果认证失败,会将控制转交给认证入口点(通过authenticationEntryPoint属性装配)
<bean id="basicProcessingFilter" class="org.acegisecurity.ui.basicauth.BasicProcessingFilter">
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationEntryPoint" ref="basicProcessingFilterEntryPoint" />
</bean>
4) basicProcessingFilterEntryPoint
通过向浏览器发送一个HTTP401(未授权)消息,提示用户登录。
处理基于HTTP的授权过程, 在当验证过程出现异常后的"去向",通常实现转向、在response里加入error信息等功能。
<bean id="basicProcessingFilterEntryPoint"
class="org.acegisecurity.ui.basicauth.BasicProcessingFilterEntryPoint">
<property name="realmName" value="Acegi First Realm Name" />
</bean>
其中,realmName属性取值并不存在太多的实际含义,运行时,”Acegi First Realm Name“字符串会显示在IE浏览器弹出的HTTP BASIC认证对话框中。
5) exceptionTranslationFilter
异常转换过滤器,主要是处理AccessDeniedException和AuthenticationException,将给每个异常找到合适的"去向"
<bean id="exceptionTranslationFilter"
class="org.acegisecurity.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint" ref="basicProcessingFilterEntryPoint" />
</bean>
在此,如果认证不通过将会将控制转交给认证入口点(通过authenticationEntryPoint属性装配)
6) authenticationManager
起到认证管理的作用,它将验证的功能委托给多个Provider,并通过遍历Providers, 以保证获取不同来源的身份认证,若某个Provider能成功确认当前用户的身份,authenticate()方法会返回一个完整的包含用户授权信息的Authentication对象,否则会抛出一个AuthenticationException。
Acegi提供了不同的AuthenticationProvider的实现,如:
DaoAuthenticationProvider 从数据库中读取用户信息验证身份
AnonymousAuthenticationProvider 匿名用户身份认证
RememberMeAuthenticationProvider 已存cookie中的用户信息身份认证
AuthByAdapterProvider 使用容器的适配器验证身份
CasAuthenticationProvider 根据Yale中心认证服务验证身份, 用于实现单点登陆
JaasAuthenticationProvider 从JASS登陆配置中获取用户信息验证身份
RemoteAuthenticationProvider 根据远程服务验证用户身份
RunAsImplAuthenticationProvider 对身份已被管理器替换的用户进行验证
X509AuthenticationProvider 从X509认证中获取用户信息验证身份
TestingAuthenticationProvider 单元测试时使用
每个认证者会对自己指定的证明信息进行认证,如DaoAuthenticationProvider仅对UsernamePasswordAuthenticationToken这个证明信息进行认证。
<bean id="authenticationManager"
class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider" />
</list>
</property>
</bean>