读书人

acegi参照的部分翻译

发布时间: 2012-07-08 17:43:42 作者: rapoo

acegi参考的部分翻译

每个"安全对象"拦截器(下文中称为"保护性拦截器")作用于一个特殊类型的"安全对象"。那么,什么是安全对象?安全对象是指对它采取了安全保护措施的任何类型的对象。一个安全对象必须提供某种形式回调,这样当需要的时候保护性拦截器就能明显地起作用。保护性拦截器回调对象同时继续所请求的操作。如果安全对象不能提供一个本地的回调方法,就要写一个包装器来实现它。

每个安全对象都有一个实现它的包放在org.acegisecurity.intercept包中。在安全系统中的每个其它包是一个独立的安全对象.因此它能支持上述的任何一种安全对象.

只有那些想对拦截和认证请求采用全新方法的开发者才需要直接使用安全对象.例如有可能建立一个新的安全对象来对没有使用MethodInvocations 对象的消息系统提供安全保护.大多数的Spring应用将简单地完全透明地使用三种普遍支持安全对象类型((AOP Alliance MethodInvocation, AspectJ 连接点 和 web 请求过滤拦截器)

Acegi安全系统中八个关键部分的每个部分都将在本文中详细讨论.

1.3.2 所支持的安全对象

如图1所示,目前Acegi安全系统支持三种安全对象.
第一种对象处理AOP AllianceMethodInvocation.这种安全对象用于保护SpringBean.开发者通常用它来保护他们的业务对象.为了生成一个标准的Spring-hosted类型的bean用作MethodInvocation,Bean简单地通过 ProxyFactoryBean 或者BeanNameAutoProxyCreator 或者DefaultAdvisorAutoProxyCreator来公布.大多数Spring开发者对此都已很熟悉,因为他们使用过Spring的事务处理和Spring的其它方面.

第二种对象是AspectJ连接点对象.AspectJ在域对象实例安全方面有一种特殊的应用,这通常是在 Springbean容器之外.通过使用AspectJ,利用标准的构造函数,如new Person(),Acegi 安全系统对他们提供安全保护.AspectJSecurityInterceptor仍然由Spring管理.它创建Aspect单例,并通过适当的认证管理器、存取判别管理器等将它联系起来。

第三种是过滤器调用(FilterInvocation)对象.它包含在Acegi安全系统内。它由一个包含的过滤器创建并简单地封装了HTTPServletRequest、ServletResponse和FilterChain。过滤器调用对象对HTTP资源提供了安全保护。开发者通常不需要了解它的工作机制,因为他们只要在他们的web.xml中添加过滤器来让安全系统工作。

1.3.3配置属性

每一个安全对象都能作用于一些特殊的请求。例如,MethodInvocation能用于对带有任意参数的任何方的的调用。而FilterInvocation能用在任何的HTTP URL上。

Acegi 安全系统需要记录一些配置信息,这些配置信息用于各种可能的请求。例如BankManager.getBalance (intaccountNumber)请求所需的安全配置与BankManager.approveLoan (intapplicationNumber)请求所需的安全配置有很大的不同。与此类似,
如图3所示,Acegi安全性系统包括几个具体的认证(Authentication)实现类:

UsernamePasswordAuthenticationToken 允许使用用户名(username)和密码(password)来表示调用者(principal)和他的证书(credentials)。它们也是由 HTTP Session Authentication负责创建的。 TestingAuthenticationToken 主要用作单元测试,它会为相应的AuthenticationProvider自动考虑一个认证对象。 RunAsUserToken 被作为默认的run-as认证置换实现。这个将在Run-As Authentication Replacement那节中进一步讨论。 CasAuthenticationToken 用于描述一次成功的耶鲁集中认证服务 (CAS)。这将在CAS章节中进一步讨论。 PrincipalAcegiUserToken 和JettyAcegiUserToken 实现了AuthByAdapter (Authentication的子类)并且它们是在认证过程已经被 Acegi系统的容器适配器完成后被使用的。这部分也将在容器适配器章节中作进一步讨论。

对于主体(principal)的授权工作是通过GrantedAuthority进行的。GrantedAuthority接口将在下面关于授权的章节中被讨论。

1.6.2 认证管理器

在安全拦截器一节中我们提到AbstractSecurityInterceptor从SecurityContextHolder中的SecurityContext里面提取Authentication对象。紧接着就将它传递给AuthenticationManager。AuthenticationManager接口十分的简单:

public Authentication authenticate(Authentication authentication) throws AuthenticationException;

AuthenticationManager的实现在认证失败的时候会抛出一个异常(AuthenticationException),或者成功时返回一个组装成功的Authentication对象。特别要注意,返回的Authentication对象应该包括一组GrantedAuthority对象。安全拦截器将返回的、组装后的Authentication对象放回到SecurityContextHolder中的SecurityContext里,用以替换原来的那个Authentication对象。

AuthenticationException有几个子类,其中最重要的是 BadCredentialsException(主体(principal)或者(证据)credentials错误),DisabledException和LockedException.后面两个异常表示主体已经发现(principal)但是证据没有通过检验还有认证被否决、拒绝。AuthenticationServiceException也会被使用,它表明认证系统不能处理请求(例如数据库不可用引起)。AuthenticationException 还有CredentialsExpiredException和AccoungtExpiredException两个子类,虽然它们不是很常用。

1.6.3 基于供方的认证

尽管最基本的Authentication和AuthenticationManager接口使用户可以开发出自己的认证系统,但是用户完全可以考虑使用 Acegi安全系统提供的基于供方的认证包。其关键类??ProviderManager通过一组认证提供者(AuthenticationProviders)的形式在bean定义中被配置:

<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"><property name="providers"><list><ref bean="daoAuthenticationProvider"/><ref bean="someOtherAuthenticationProvider"/></list></property></bean

ProviderManager将调用一系列已注册的AuthenticationProvider实现,直到找到一个表明它能够认证给定的Authentication类为止。当找到第一个符合条件的AuthenticationProvider时,它就把它传递给认证请求。AuthenticationProvider要么抛出一个AuthenticationException异常,要么返回一个组装成功的Authentication对象.

ProviderManager还有几个其它重要的函数,它集成了并发会话处理支持,它也能将任何由AuthenticationProvider抛出的异常转化和发布一个恰当的事件。这些事件可在org.acegisecurity.event.authentication包中找到。高级用户能够配置ProviderManager.exceptionMappings属性从而将不同的异常映射为不同的事件(通常不需要这么做,缺省的事件传播是恰当的??特别是当你没在ApplicationContext中配置ApplicationListener时,事件就会简单地忽略掉)

Acegi安全系统所提供的几个AuthenticationProvider实现类:

TestingAuthenticationProvider能够对TestingAuthenticationToken进行验证。这种认证的限制是它不管TestingAuthenticationToken中包含什么,它都认为是有效的。这就使得它在进行单元测试时变得非常有用,因为你可以创建一个Authentication对象---它正好对你需要进行测试的方法进行了授权。这样你就可以不需要在产品系统中注册AuthenticationProvider而能完成需要的测试环境搭建了。

DaoAuthenticationProvider 可以对通过对数据库数据的存取,验证UsernamePasswordAuthenticationToken。这个方面将在下面的章节进行讨论,因为它是进行验证处理的主要工作方式。 RunAsImplAuthenticationProvider 用以验证RunAsUserToken。这个将在下面Run-As Authentication Replacement章节进行讨论。如果你不使用 run-as处理机制,你不需要注册此AuthenticationProvider。 AuthByAdapterProvider 能够验证任何的AuthByAdapter (a subclass of Authentication used with containeradapters)。这部分内容将在下面的章节进行讨论。如果你不使用容器适配器,你不需要注册此AuthenticationProvider。 CasAuthenticationProvider 用来验证CAS,将在下面章节进行讨论。 JaasAuthenticationProvider 将会将认证请求指派到JAAS登录模块,这将在下文进行讨论。 1.6.4 并发会话支持

Acegi安全系统具有阻止同一主体并发访问同一web应用资源的能力。例如:你可以阻止用户"batman"同一时间内两次进行系统登录。

为了使用并发会话支持,你需要在web.xml是加入下列语句:

<listener><listener-class>org.acegisecurity.ui.session.HttpSessionEventPublisher</listener-class></listener>

另外,你需要将org.acegisecurity.concurrent.ConcurrentSessionFilter加入到你的FilterChainProxy中。并发会话过滤器需要配置唯一一个sessionRegistry的属性,它通常指向SessionRegistryImpl实例。

每次HttpSession开始或终止时,web.xml中的HttpSessionEventPublish都会产生一个ApplicationEvent事件并通知Spring的ApplicationContext.这非常关键,因为它允许SessionRegistryImpl注意到会话会在何时结束。

你也需要建立ConcurrentSessionControllerImpl,并在ProviderManager中引用它。

<bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager"><property name="providers"><!-- your providers go here --></property><property name="sessionController"><ref bean="concurrentSessionController"/></property></bean><bean id="concurrentSessionController" class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl"><property name="maximumSessions"><value>1</value></property><property name="sessionRegistry"><ref local="sessionRegistry"/></property></bean><bean id="sessionRegistry" class="org.acegisecurity.concurrent.SessionRegistryImpl"/>
1.6.5 数据存取对象认证提供者

Acegi安全系统包含一个产品级的认证提供者(AuthenticationProvider)实现??DaoAuthenticationProvider,这个认证提供者通过获得在创建bean时配置在数据存取对象中的认证详细信息,从而能够认证UsernamePasswordAuthenticationToken

<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"><property name="userDetailsService"><ref bean="inMemoryDaoImpl"/></property><property name="saltSource"><ref bean="saltSource"/></property><property name="passwordEncoder"><ref bean="passwordEncoder"/></property></bean>

其中PasswordEncoder和SaltSource是可选的,PasswordEncoder负责对认证库中的密码进行加解密.而SaltSource则是在产生密码时给它加点"盐",以增强密码在认证库中的安全性.Acegi安全系统提供的PasswordEncoder实现中包括MD5、SHA和明文编码。Acegi安全系统也提供两个SaltSource的实现:SystemWideSaltSource,它用同样的"盐"对系统中所有的密码进行编码,而ReflectionSaltSource只对从UserDetails对象返回的获得这种"盐"的指定属性进行检查。请参考JavaDoc以获取对这些可选特性的更详细信息。

除上属性外,DaoAuthenticationProvider也支持对UserDetails对象的缓存。UserCache接口使DaoAuthenticationProvider能把UserDetails对象放进缓存并可在接下来对相同用户进行认证时在缓存中找回它。在缺省时DaoAuthenticationProvider使用NullUserCache,表示没有使用Cache.Acegi也提供了一个可用的缓存实现??EhCacheBasedUserCache,其配置如下:

<bean id="daoAuthenticationProvider" class="org.acegisecurity.providers.dao.DaoAuthenticationProvider"><property name="userDetailsService"><ref bean="userDetailsService"/></property><property name="userCache"><ref bean="userCache"/></property></bean><bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"><property name="configLocation"><value>classpath:/ehcache-failsafe.xml</value></property></bean><bean id="userCacheBackend" class="org.springframework.cache.ehcache.EhCacheFactoryBean"><property name="cacheManager"><ref local="cacheManager"/></property><property name="cacheName"><value>userCache</value></property></bean><bean id="userCache" class="org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache"><property name="cache"><ref local="userCacheBackend"/></property></bean>

所有Acegi安全系统的EH-CACHE实现中(包括EhCacheBasedUserCache),都需要一个EH-CACHEcache对象,这个cache对象可在你喜欢的任何地方获得,虽然我们推荐你使用Spring的工厂类如上配置中所示。如使用Spring的工厂类,请参考Spring文档以获取如何优化的更详细的细节,如缓存存储本地化、内存使用、退出策略、超时设定等。

一个能为DaoAuthenticationProvider提供存取认证库的的类,它必须要实现UserDetailsService接口:

public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;

UserDetails是一个接口,它能提供一系列get函数以获得认证时需要的基本认证信息如用户名、密码、所获得的授权、是否禁用等;一个具体的实现就是User类.Acegi用户需要决定什么时候写他们的UserDetailsService接口以及返回的UserDetails是什么类型。在大多数情况下将使用User及其子类,虽然在特定的环境中(如对象关系映射器)也许需要用户写他们自己的UserDetails实现。UserDetails也经常用于存储一些与调用者相关的附加信息(如电话号码、email地址等)因此它们经常在web视图中使用。

如果UserDetailsService实现起来很简单,用户应当很容易从他们选择的持久化策略中找回认证信息。

DaoAuthenticationProvider设计没有考虑支持帐户锁定的功能,因为那将增加UserDetailsService接口的复杂性。例如需要增加不成功认证的计数,这些功能可能通过补充应用程序的公布特性而很容易提供,这些特性将在下面讨论。

DaoAuthenticationProvider返回一个Authentication对象,它含有principal的属性集。principal要么是一个字串(是必需的用户名),要么是一个UserDetails对象(从UserDetailsService中查找),缺省情况下返回UserDetails。因为这将使应用能加上额外的属性以便在应用中使用,如用户的全名,Email地址等。如使用容器适配器,或在应用中使用Strings(在Acegi0.6之前的版本就是这样)你就应在你的应用上下文中把DaoAuthenticationProvider.forcePrincipalAsString属性设为true。

1.6.6 In-Memory 认证

虽然使用DaoAuthenticationProvider,从持久化引擎中获取信息来创建定制的UserDetailsService实现很容易,但许多应用不需要这么复杂,一种替代方式是使用InMemoryDaoImpl在应用上下文中配置认证库:

<bean id="inMemoryDaoImpl" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl"><property name="userMap"><value>      marissa=koala,ROLE_TELLER,ROLE_SUPERVISOR      dianne=emu,ROLE_TELLER      scott=wombat,ROLE_TELLER      peter=opal,disabled,ROLE_TELLER</value></property></bean>

1.6.7 JDBC认证
1.6.8 JAAS认证
1.6.9 Siteminder认证
1.6.10 使用认证的几点建议

读书人网 >开源软件

热点推荐