Acegi提供了四项重要组件,在学习Acegi之前一定需要了解想、清楚:
AbstractSecurityInterceptor(安全拦截器):借助于安全拦截器能够实现对客户请求的拦截,进而对用户进行认证、授权,或者给用户赋予不同的角色。
AuthenticationManager(认证管理器):借助于认证管理器,能够实现对用户身份的识别。通常,它需要借助于用户名(Principal)及密码(Credential,凭证)进行认证。
AccessDecisionManager(访问决策管理器),借助于访问决策管理器,能够实现对预访问资源的授权。如果用户对应的角色不满足目标资源的安全性需求,则将不能够访问到它。
RunAsManager(Run-As管理器),能够更换用户对应的角色(在标准的JAVA EE Web应用和EJB应用中,也存在类似的行为)。在客户访问如:Servlet、EJB、POJO等资源(服务提供者)的同时,这些资源也可能被其他资源的用户直接或者地访问。因此,需要对用户对应的角色进行调整,这就是Run-As管理器所扮演的角色。
Acegi sample的学习
首先三个配置文件的作用:
applicationContext-acegi-security.xml
applicationContext-common-business.xml
applicationContext-common-authorization.xml
这三个配置文件会在web.xml中事先声明。
applicationContext-acegi-security.xml 中的配置。
ProviderManager的作用,先看看示例:
<!-- ======================== AUTHENTICATION ======================= -->
<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
<property name="providers">
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<ref local="rememberMeAuthenticationProvider"/>
</list>
</property>
</bean>
ProviderManager是认证管理器(AuthenticationManager)的一个适用于大多数情况的实现。它将身份验证的责任委托给一个或多个认证提供者。上面的例子中,用到的三个认证提供者全部是由org.acegisecurity.providers.AuthenticationProvider定义的。由于上面用到了三个认证提供者,那么可以根据这三个身份认证提供者所具有的三方面身份认证源来提供认证,逐一遍历这个集合,直到某个人认证提供者能够成功地验证该用户的身份。
DaoAuthenticationProvider,使用DaoAuthenticationProvider可以进行简单的基于数据库的身份验证(那么,我们做实验的时候,可以只写这样一个提供者就可以)。看示例:
<bean id="daoAuthenticationProvider"
class="org.acegisecurity.providers.dao.DaoAuthenticationProvider">
<property name="userDetailsService">
<ref local="jdbcDaoImpl" />
</property>
<property name="userCache">
<ref local="userCache" />
</property>
<property name="passwordEncoder">
<ref local="passwordEncoder" />
</property>
</bean>
在上面的
<property name="userDetailsService">
<ref local="jdbcDaoImpl" />
</property>
部分,指定了一个用于从数据库中获取用户信息的Bean。这个Bean我们可以指定为jdbcDaoImpl,也可以通过赋予authenticationDao,然后用jdbcDaoImpl来实现,其实jdbcDaoImpl是authenticationDao的一个实例。
<bean id="jdbcDaoImpl" class="org.acegisecurity.userdetails.jdbc.JdbcDaoImpl">
<property name="dataSource">
<ref bean="dataSource" />
</property>
</bean>
其实上面的property userDetailsService,我们还可以用一个简单的内存Dao(InMemoryDaoImpl)来实现,但是这种方式我不喜欢,这里不阐述。
userCache与passwordEncoder,passwordEncoder是一中加密方式,可选。userCache是缓存用户信息而用的。
FILTER CHAIN的作用。先看看示例:
<!-- ======================== FILTER CHAIN ======================= -->
<!-- if you wish to use channel security, add "channelProcessingFilter," in front
of "httpSessionContextIntegrationFilter" in the list below -->
<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,basicProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor,switchUserProcessingFilter
</value>
</property>
</bean>
首先,这个是一个过滤器,我们想让它生效,就必须在web.xml中声明<filter>和<filter-mapping>来配置它们:
<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>
如果我们这个过滤器必须引入一个Bean来完成它的工作。那么,由于web.xml并没有spring的Ioc功能,所以我们不能完成它(抛去在Servlet过滤器中编写Spring特定代码不说)。Acegi通过FilterToBeanProxy提供了更好的解决方法。其实上面的示例已经是一个FilterToBeanProxy过滤器了。那么我们只需要在Spring配置文件中配置真正的过滤器就可以了,因为FilterToBeanProxy将自己的工作委托给了Spring应用上下文中的Bean来完成。你可能不知道<filter-mapping>的作用,它是指,将过滤器与一个URL模式相关联,所有的请求都将被该过滤器处理。(/*是所有Acegi过滤器推荐的URL模式,这样做是说Acegi应该拦截所有的请求,并由其依赖的安全管理器来决定是否和如何保护请求。)
httpSessionContextIntegrationFilter:每次request前 HttpSessionContextIntegrationFilter从Session中获取Authentication对象,在request完后, 又把Authentication对象保存到Session中供下次request使用,此filter必须其他Acegi filter前使用,使之能跨越多个请求。这些就犹如在web.xml声明一系列的过滤器,不过当把他们都声明在spring中就可以享受Spring给我们带来的方便了。
a. logoutFilter:用户的注销
b. authenticationProcessingFilter:处理登陆请求
c. basicProcessingFilter:
d. securityContextHolderAwareRequestFilter:
e. rememberMeProcessingFilter:
f. anonymousProcessingFilter:
g. exceptionTranslationFilter:异常转换过滤器
h. filterInvocationInterceptor:在访问前进行权限检查
i. switchUserProcessingFilter: