`
xyz20003
  • 浏览: 289613 次
  • 性别: Icon_minigender_1
  • 来自: 唐山
社区版块
存档分类
最新评论

(翻译)Spring Security-2.0.x参考文档“Remember-Me认证”

阅读更多
Remember-Me认证
14.1. 概述

记住我(remember-me)或持久登录(persistent-login)认证,指的是网站可以在不同会话之间记忆验证的身份。 通常情况是发送一个cookie给浏览器,在以后的session里检测cookie,进行自动登录。 Spring Security为remember-me实现提供了必要的调用钩子,并提供了两个remember-me的具体实现。 其中一个使用散列来保护基于cookie标记的安全性,另一个使用了数据库或其他持久化存储机制来保存生成的标记。

注意,两个实现方式,都需要UserDetailsService。 如果你使用了认证提供器,没有使用UserDetailsService(比如LDAP供应器),那它就没法工作,除非你在application context里设置了一个UserDetailsService。
14.2. 简单基于散列标记的方法

这种方法使用散列来完成remember-me策略。 本质上,在成功进行认证的之后,把一个cookie发送给浏览器,使用的cookie组成结构如下:

    base64(username + ":" + expirationTime + ":" + md5Hex(username + ":" + expirationTime + ":" password + ":" + key))

    username:         As identifiable to the UserDetailsService
    password:         That matches the one in the retrieved UserDetails
    expirationTime:   The date and time when the remember-me token expires, expressed in milliseconds
    key:              A private key to prevent modification of the remember-me token
       

这个remember-me标记只适用于指定范围,提供用户名,密码和关键字都不会改变。 值得注意,这里有一个潜在的安全问题,来自任何一个用户代理的remember-me标记,直到标记过期都是可用的。 这个问题和摘要式认证相同。 如果一个用户发现标记已经设置了,他们可以轻易修改他们的密码,并且立即注销所有的remember-me标记。 如果需要更好的安全性,你应该使用下一章描述的方法。 或者不应该使用remember-me服务。

如果你还记得在命名空间配置中讨论的主题,你只要添加<remember-me>元素就可以使用remember-me认证:

  <http>
    ...
    <remember-me key="myAppKey"/>
  </http>
 
               

如果你使用了auto-config设,它也会自动启用。 这个UserDetailsService会自动选上。 如果你在application context中配置了多个,你需要使用user-service-ref属性指定应该使用哪一个,这里的值要放上你的UserDetailsService bean的名字。
14.3. 持久化标记方法

这个方法是基于这篇文章 http://jaspan.com/improved_persistent_login_cookie_best_practice 进行了一些小修改 [3]。 要用在命名空间配置里使用这个方法,你应该提供一个datasource引用:

  <http>
    ...
    <remember-me data-source-ref="someDataSource"/>
  </http>
 
           

数据应该包含一个 persistent_logins 表,可以使用下面的SQl创建(或等价物):

    create table persistent_logins (username varchar(64) not null, series varchar(64) primary key, token varchar(64) not null, last_used timestamp not null)

14.4. Remember-Me接口和实现

Remember-me认证不能和基本认证一起使用,因为基本认证往往不使用HttpSession。 Remember-me使用在AuthenticationProcessingFilter中,通过在它的超类AbstractProcessingFilter里实现的一个调用钩子。 这个钩子会在合适的时候调用一个具体的RememberMeServices。 这个接口看起来像这样:

  Authentication autoLogin(HttpServletRequest request, HttpServletResponse response);
  void loginFail(HttpServletRequest request, HttpServletResponse response);
  void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication);
   

请参考JavaDocs获得有关这些方法的完整讨论,不过注意在这里,AbstractProcessingFilter只调用loginFail() 和 loginSuccess()方法。 当SecurityContextHolder没有包含Authentication的时候,RememberMeProcessingFilter才去调用autoLogin()。 因此,这个接口通过使用完整的认证相关事件的提醒提供了下面remember-me实现,然后在可能包含一个cookie希望被记得的申请web请求中调用这个实现。 这个设计允许任何数目的remember-me实现策略。 我们在下面看看上面介绍过的两个Spring Security提供的实现。
14.4.1. TokenBasedRememberMeServices

这个实现支持在Section 14.2, “简单基于散列标记的方法”里描述的简单方法。 TokenBasedRememberMeServices被 RememberMeAuthenticationProvider执行的时候生成一个RememberMeAuthenticationToken。 认证提供器和TokenBasedRememberMeServices之间共享一个key。 另外TokenBasedRememberMeServices需要一个UserDetailsService,用它来获得用户名和密码,进行比较,然后生成RememberMeAuthenticationToken来包含正确的GrantedAuthority[]。 如果用户请求注销,让cookie失效,就应该使用系统提供的一系列注销命令。 TokenBasedRememberMeServices也实现Spring Security的LogoutHandler接口,这样可以使用LogoutFilter自动清除cookie。

这些bean要求在application context里启用remember-me服务,像下面一样:

<bean id="rememberMeProcessingFilter"
    class="org.springframework.security.ui.rememberme.RememberMeProcessingFilter">
  <property name="rememberMeServices" ref="rememberMeServices"/>
  <property name="authenticationManager" ref="theAuthenticationManager" />
</bean>

<bean id="rememberMeServices" class="org.springframework.security.ui.rememberme.TokenBasedRememberMeServices">
  <property name="userDetailsService" ref="myUserDetailsService"/>
  <property name="key" value="springRocks"/>
</bean>

<bean id="rememberMeAuthenticationProvider"
    class="org.springframework.security.providers.rememberme.RememberMeAuthenticationProvider">
  <property name="key" value="springRocks"/>
</bean>

           

不要忘记把你的RememberMeServices实现添加到AuthenticationProcessingFilter.setRememberMeServices()属性中,包括把RememberMeAuthenticationProvider添加到你的AuthenticationManager.setProviders()队列中,把RememberMeProcessingFilter添加到你的FilterChainProxy中(要放到AuthenticationProcessingFilter后面)。
14.4.2. PersistentTokenBasedRememberMeServices

这个类可以像TokenBasedRememberMeServices一样使用,但是它还需要配置一个PersistentTokenRepository来保存标记。 这里有两个标准实现。

    *

      InMemoryTokenRepositoryImpl最好是只用来测试。
    *

      JdbcTokenRepositoryImpl把标记保存到数据库里。

数据库表结构在 Section 14.3, “持久化标记方法”.

[3] 基本上,为了防止暴露有效登录名,用户名没有包含在cookie里。在这个文章的评论里有一个相关的讨论。
分享到:
评论
1 楼 supercrsky 2008-10-28  
怎么设置cookie失效的时间呢?比如两个星期

相关推荐

Global site tag (gtag.js) - Google Analytics