Acegi配置信息讲解

1. 概述 
Acegi是一个专门为SpringFramework应用提供安全机制的开放源代码项目,全称为Acegi Security System for Spring,当前版本为 
0.8.3。它使用了Spring的方式提供了安全和认证安全服务,包括使用Bean Context,拦截器和面向接口的编程方式。通过精心 
配置Acegi安全系统能够轻松地适用于复杂的安全需求。它既能应用于WEB应用也能应用于非WEB应用。在 本文的示例程序 
里,我将演示如何将Acegi应用于WEB应用程序。通过这个例子详细介绍如何配置Acegi的各个组件,同时介绍如何扩展Acegi 
使其能够从数据库中读取配置信息。

2. 例子说明 
本文的例子是一个联系人管理程序,使用SpringFramework 1.2.4 和 Acegi0.8.3,数据库采用Mysql。程序的目录结构如下:   
acegi-sample 
│ contactadd.jsp//增加联系人页面 
│ contactedit.jsp//编辑联系人页面 
│ contactlist.jsp//联系人列表页面 
│ contactmainterance.jsp//联系人操作页面 
│ index.jsp//主页面 
│ login.jsp//登录页面 
│ logoff.jsp//登出页面 
│
├─WEB-INF 
│ │ web.xml 
│ │ applicationContext-basic.xml 
│ │ applicationContext-security-acegi.xml 
│ │ log4j.properties 
│ │ 
│ ├─src 
│ │ └─sample//java代码目录 
│ ├─classes 
│ └─lib//依赖包目录 
└─db//建表脚本目录 

3.配置文件说明 
接下来,我们将进入本文的重要内容,开始对Acegi应用程序所牵涉到的配置文件进行一一说明。 

3.1 web.xml 
首先声明SpringFramework的配置文件列表。为了便于管理,将业务方法相关的配置文件和Acegi安全配置相关的配置文件分 
开。   

  
contextConfigLocation 

/WEB-INF/applicationContext-basic.xml 
/WEB-INF/applicationContext-security-acegi.xml 


其次声明Acegi过滤器。   
<!--Acegi Filter Chain Proxy -->

Acegi Filter Chain Proxy 
net.sf.acegisecurity.util.FilterToBeanProxy 

targetClass 
net.sf.acegisecurity.util.FilterChainProxy 



Acegi Filter Chain Proxy 
/* 

说明:Acegi对WEB应用的支持主要是依靠servlet 过滤器(filter) 来实现的。每一个http request都将被这些过滤器层层拦截 并 
进行安全处理(包括认证和授权)。针对不同的安全处理,Acegi提供了不同的过滤器。过滤器的配置信息位于web.xml,但是 
我们又希望把Acegi的过滤器配置信息放在SpringFramework的配置文件里(applicationContext-security-acegi.xml),从而实现对 
这些过滤器的“控制反转”。解决这个问题的方法是采用Acegi提供的FilterToBeanProxy。FilterToBeanProxy顾名思义就是对 
Acegi过滤器Bean的代理,它的主要功能就是将http请求依次分派给对应的过滤器Bean。 
3.2 applicationContext-security-acegi.xml 
applicationContext-security-acegi.xml主要包括认证相关配置信息和WEB资源授权配置信息。首先是声明过滤器序列。   



CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON 
PATTERN_TYPE_APACHE_ANT 
/**=httpSessionContextIntegrationFilter,authenticationProcessingFilter,anonymousProcessingFilter,securityEnforcementFilter 



各个过滤器的作用如下: 
httpSessionContextIntegrationFilter 
根据session中存放的信息组装ContextHolder。ContextHolder主要用于存放SecureContext, 
包括用户的权限信息 
authenticationProcessingFilter 处理认证请求(通常是一个登录页面的表单请求) 

anonymousProcessingFilter 
匿名用户处理。如果用户尚未登录,将生成一个匿名用户的Authentication存放到 
ContextHolder中 
securityEnforcementFilter 强制安全验证过滤器。验证所请求的url是否在用户的权限范围内。 
3.2.1 httpSessionContextIntegrationFilter相关配置信息 
 

net.sf.acegisecurity.context.security.SecureContextImpl

说明: context属性指定context的实现类。 
3.2.2 authenticationProcessingFilter相关配置信息 
authenticationProcessingFilter的配置比较复杂,我们通过下图来看一下: 
authenticationProcessingFilter配置说明: 

authenticationManager 认证管理器 
authenticationFailureUrl 认证失败后,重定向的url 
defaultTargetUrl 认证成功后,重定向的url 
filterProcessesUrl 
该过滤器拦截的url,通常是/j_acegi_security_check,和登录页面(login.jsp)的登录表单的action相 
同 
authenticationManager(认证管理器)用于管理AuthenticationProvider(认证提供者)。它的作用是使你能够通过多个不同的认 
证管理源来对用户进行认证。认证管理器将依次调用认证提供者的认证方法,直到认证通过。本程序使用两种认证提供者。 
authenticationManager配置说明: 
daoAuthenticationProvider 基于数据库的认证提供者。 
anonymousAuthenticationProvider 用于认证匿名用户。 
daoAuthenticationProvider主要功能是从数据库取出用户名和密码,判断登录信息是否正确,如果是,则取出用户权限等用户 
信息,并且存放到cache中,以便以后再次使用。具体流程可以参考:DaoAuthenticationProvider的authenticate方法。 
daoAuthenticationProvider配置说明: 
authenticationDao 认证数据访问对象,用于获取用户信息,包括:用户名,用户密码,用户状态和用户权限。 
userCache 用户信息cache实现bean 
jdbcDaoImpl是认证数据访问对象,它能够从默认的数据库结构中获取用户信息,由于Acegi默认的数据库结构和本程序的不 
同,因此需要修改jdbcDaoImpl的默认sql。注意,采用这种方式能够使Acegi很好的兼容旧的应用程序,因为它对底层的数据结 
构并没有强制要求。jdbcDaoImpl配置说明: 
dataSource 数据源bean 
usersByUsernameQuery 用户信息查询sql 
authoritiesByUsernameQuery 用户权限查询sql 
userCache用于定义用户信息cache功能的提供者。userCache配置说明: 
cache 定义ehcache工厂bean 
本程序采用ehcache作为cache实现。由于认证管理器在每次对http请求进行认证之前都会查找用户信息,通过使用cache就可以 
避免每次都重复访问数据库。 
3.2.3 anonymousProcessingFilter相关配置信息: 
foobar
anonymousUser,AUTH_ANONYMOUS
说明:anonymousProcessingFilter的作用是判断ContextHolder中是否有Authentication对象,如果没有就创建一个Authentication对 
象,其中包含的用户名是anonymousUser,用户权限是AUTH_ANONYMOUS。这使得没有登录的匿名用户能够自动的获得匿 
名的用户名和权限。 
3.2.4 securityEnforcementFilter相关配置信息 

securityEnforcementFilter的配置比较复杂
securityEnforcementFilter配置说明: 
filterSecurityInterceptor 实现对URL资源进行授权访问。 
authenticationEntryPoint 配置登录界面信息。 
securityEnforcementFilter的作用主要是将http请求转发给filterSecurityInterceptor,由filterSecurityInterceptor来对HTTP请求的合法 
性进行判断。 
filterInvocationInterceptor配置说明: 
authenticationManager 认证管理器 
accessDecisionManager 投票通过策略管理器 
objectDefinitionSource 
URL的权限配置信息。用于指定不同的URL资源对应的权限。配置如下: 
/**/*.jpg=AUTH_ANONYMOUS,AUTH_USER 
/**/*.gif=AUTH_ANONYMOUS,AUTH_USER 
/**/*.png=AUTH_ANONYMOUS,AUTH_USER 
/login.jsp*=AUTH_ANONYMOUS,AUTH_USER 
/**=AUTH_USER 
以上配置指定AUTH_ANONYMOUS权限的用户(即匿名用户)只可以访问图片资源和登录页 
面,AUTH_USER权限的用户可以访问全部WEB资源。 
accessDecisionManager(访问决策管理器)首先通过authenticationManager判断用户是否通过认证(即是否已经登录),然后根 
据objectDefinitionSource的配置信息调用accessDecisionManager对用户权限进行投票。 
httpRequestAccessDecisionManager配置说明: 
allowIfAllAbstainDecisions 设定是否允许:“没人反对就通过”的投票策略 
decisionVoters 投票者 

httpRequestAccessDecisionManager(投票通过策略管理器)用于管理投票通过策略。Acegi提供三种投票通过策略的实现: 
AffirmativeBased(至少一个投票者同意方可通过),ConsensusBased(多数投票者同意方可通过),UnanimousBased(所有投 
票者同意方可通过)。本程序采用AffirmativeBased策略,并且禁止“没人反对就通过”的投票策略。 
roleVoter配置说明: 
rolePrefix 
该投票者支持的权限前缀,默认是“ROLE_”,本程序所有的权限字符串均以“AUTH_”开头, 
故设为“AUTH_” 
通过设定rolePrefix可以指定roleVoter所支持的权限范围。 
3.3 applicationContext-basic.xml 
applicationContext-basic.xml主要包括数据访问对象,业务方法,业务方法安全管理拦截器的配置信息。主要讲解业务方法安全管理拦截器(MethodSecurityInterceptor)的相关配置,其它的配置就不再赘述了,请参考相关文 
档。 
3.3.1 contactManager相关配置信息 
  
sample.service.IContactManager
contactManager的实现类是ProxyFactoryBean(代理工厂),它使用Spring AOP技术拦截代理接口里的方法,并依次执行拦截器 
列表里的拦截器对应的操作。contactManager有事务拦截器和业务方法安全拦截器。 
3.3.2 contactManagerSecurity相关配置信息 
authenticationManager 认证管理器 
accessDecisionManager 
投票通过策略管理器,和filterInvocationInterceptor采用相同的策略管理器,在实际项目中,如果有 
需要可以采用不同的策略管理器。 
objectDefinitionSource 业务方法的权限配置信息。用于指定不同的业务方法资源对应的权限。 
注意:contactManagerSecurity的实现类是MethodSecurityInterceptor,缺省情况下MethodSecurityInterceptor的 
objectDefinitionSource属性是通过net.sf.acegisecurity.intercept.method.MethodDefinitionSourceEditor来设置的。 
MethodDefinitionSourceEditor只支持属性配置文件的格式(同filterInvocationInterceptor的objectDefinitionSource属性),而实际 
情况中,由于业务方法比较多,显然配置信息存放在数据库中比较好。因此,我们通过注册一个CustomEditorConfigurer来修 
改MethodDefinitionSource类型属 性的对应读取类。配置如下:   
DataSourceMethodDefinitionSourceEditor根据以下SQL读取业务方法安全配置信息:   
select authority,PROTECTED_RES from authorities where AUTH_TYPE='FUNCTION' and authority like 
'AUTH_FUNC_ContactManager%' 

4.总结 
在本文的示例程序中我们只对业务对象(ContactManager)进行安全保护,对业务领域对象(Contact)的访问并没有作限 
制,这是由于在Acegi框架中采用ACL(访问控制列表)技术实现这个功能,这使得一旦我们的业务领域对象数量很多的话, 
效率将变得很低,因此我们将对业务领域对象访问控制的代码放在业务对象的业务方法中。 
将业务无关的代码从业务代码中剥离,使业务代码更干净,系统结构更合理是每个开发人员的梦想。随着AOP技术的日渐流 
行和日益发展,这个梦想已经离我们不远了。本文中的例子通过结合使用SpringFramework和Acegi两种开源框架,实现了将安 
全认证和授权代码和事务代码从业务代码中分离。  
 

你可能感兴趣的:(jsp,bean,应用服务器,配置管理,Acegi)