《Spring Security3》第三章第三部分翻译上(Remember me功能实现)(转载)

Remember me

对于经常访问站点的用户有一个便利的功能就是 remember me 。这个功能允许一个再次访问的用户能够被记住,它通过在用户的浏览器上存储一个加密的 cookie 来实现的。如果 Spring Security 能够识别出用户提供的 remember me cookie ,用户将不必填写用户名和密码,而是直接登录进入系统。

 

与到目前为止我们介绍的其它功能不同, remember me 功能并不是在使用 security 命名空间方式的配置中自动添加的。让我们尝试这个功能并查看它是怎样影响登录流程的。

实现 remember me 选项

完成这个练习后,将会为用户访问 pet store 应用提供一个简单的记忆功能。

 

修改 dogstore-security.xml 配置文件,添加 <remember-me> 声明。设置 key 属性为 jbcpPetStore

 

 

Xml代码   收藏代码
  1. < http   auto-config = "true"   use-expressions = "true"  access-decision-  
  2. manager-ref = "affirmativeBased" >   
  3. …  
  4.     < remember-me   key = "jbcpPetStore" />   
  5.     < logout   invalidate-session = "true"   logout-success-url = "/"   logout-url = "/logout" />   
  6. </ http >   
 

 

如果我们现在尝试使用应用,在流程上将不会看到有任何的变化。这是因为还需要在登录 form 上添加一个输入域,以允许用户选择使用这个功能。编辑 login.jsp 文件,添加一个 checkbox ,代码如下:

 

 

Html代码   收藏代码
  1. < input   id = "j_username"   name = "j_username"   size = "20"   maxlength = "50"   type = "text" />   
  2. < br   />   
  3. < input   id = "_spring_security_remember_me"   name ="_spring_security_  
  4. remember_me" type = "checkbox"   value = "true" />   
  5. < label   for = "_spring_security_remember_me" > Remember Me? </ label >   
  6. < br   />   
  7. < label   for = "j_password" > Password </ label > :  
 

 

当我们再次登录时,如果 Remember Me 被选中,一个 Remember Me cookie 将会设置在用户的浏览器中。

如果用户关闭浏览器并重新打开访问一个 JBCP Pets 站点上需要认证的页面,他将不会再看到登录页了。请亲自试一下——登录并将 Remember Me 选项选中,收藏首页,然后重启浏览器并再次访问首页。你能发现你直接登录成功并不再需要提供凭证。

 

一些高级的用户在体验本功能时也可以使用浏览器插件如 Firecookie http://www.

softwareishard.com/blog/firecookie/ ),来管理(移除)会话 session 。这将会在你开发或校验这种类型功能时,节省你时间和提高效率。

Remember me 是怎样实现的

Remember me 功能设置了一个 cookie 在用户的浏览器上,它包含一个 Base64 编码的字符串,包含以下内容:

l  用户的名字;

l  过期的日期 / 时间;

l  一个 MD5 的散列值包括过期日期 / 时间、用户名和密码;

l  应用的 key 值,是在 <remember-me> 元素的 key 属性中定义的。

这些内容将被组合成一个 cookie 的值存储在浏览器中以备后用。

 

MD5 是一种知名的加密哈希算法。加密哈希算法将输入的数据进行压缩并生成唯一的任意长度的文字,这叫做摘要。摘要能够在以后使用,以校验不明的输入是否与生成 hash 的输入内容完全一致,此时并不需要使用原来的输入内容本身。下面的图片展示了这个过程:


 

你可以看到,未知的输入可以与存储的 MD5 哈希进行校验,并能够得出未知的输入与存储的已知输入是否匹配的结论。摘要和加密算法( encryption algorithms )的一个重要不同在于,它很难从反向工程从摘要值得到初始的数据。这是因为摘要仅仅是原始内容的一个概述或指纹( fingerprint, ),并不是全部的数据本身(它可能会很大)。

 

尽管对加密的数据不可能进行解码,但是 MD5 对一个类型的国际却很脆弱,包括挖掘算法本身的弱点以及彩虹表攻击( rainbow table attacks )。彩虹表通常会包括数百万输入值计算出来的哈希值。这使得攻击者能够寻找彩虹表中的哈希值从而确定实际值(未经过 hash 的值)。我们将会在第四章:凭证安全存储 中讲解密码安全的时,介绍防范这种攻击的一种方法。

 

关于 remember me cookie ,我们能够看到这个 cookie 的组成足够复杂,所以对攻击者来说很难造出一个仿冒的 cookie 。在第四章中,我们将会学习另一种技术来使得 remember me 功能更加安全,免受恶意攻击。

 

Cookie 的失效时间基于一个配置的过期时间段的长度。如果用户在 cookie 失效之前重新访问我们的站点,这个 cookie 将和应用设置的其它 cookie 一起提交到应用上。

 

如果存在 remember me cookie o.s.s.web.authentication.rememberme.RememberMeAuthenticationFilter 过滤器将会检查 cookie 的内容并通过检查是否为一个认证过的 remember me cookie 来认证用户(查看本章后面的 Remember me 是否安全? 章节,将会讲述这样做的原因),这个过滤器是通过 <remember-me> 配置指令添加到过滤器链中的。

 

下面的图表阐述了校验 remember me cookie 过程中涉及到的不同组件:


 

RememberMeAuthenticationFilter 在过滤器链中,位于 SecurityContextHolderAwareRequestFilter 之后,而在 AnonymousProcessingFilter 之前。正如链中的其它过滤器那样, RememberMeAuthenticationFilter 也会检查 request ,如果是其关注的,对应的操作将会被执行。

按图中所述,过滤器负责检查用户的过滤器是否 remember me cookie 作为它们请求的一部分。如果 remember me 被发现,它会是一个 Base64 的编码,期望的 MD5 哈希值通过 cookie 中的用户名和密码进行计算获得。(这里感觉有些问题,因为期望的 MD5 值应该是通过应用来进行获取,而不是提供前台过来的 cookie 计算出来的。?)如果 cookie 通过这一层的校验,用户就已经登录成功了。

 

【你可能已经意识到如果用户修改了用户名或密码,任何的 remember me token 都将失效。请确保给用户提供适当的信息,如果允许它们修改账号的那些信息。在第四章中,我们将会看到一个替代的 remember me 实现,它只依赖用户名并不依赖密码。】

 

我们看到 RememberMeAuthenticationFilter 依赖一个 o.s.s.web.authentication.RememberMeServices 的实现来校验 cookie 。如果登录请求的 request 包含一个名为 _spring_security_remember_me form 参数,相同的实现类也会于 form 登录成功时使用。这个 cookie 用上面提到的信息进行编码,以 Base64 编码存储在浏览器中,包含了时间戳和用户密码等信息形成的 MD5 哈希值。

 

需要记住的是,可以区分通过 remember me 认证的用户和提供用户名和密码(或相当凭证)认证的用户。我们将会在审查 remember me 功能的安全性的时,对其进行简单的实验。

Remember me 与用户的生命周期

RememberMeServices 的实现在用户的生命周期中(一个认证用户 session 的生命周期)在好几个地方被调用。为了使你理解 remember me 功能,了解 remember me service 完成生命周期功能的时间点将会有所帮助:

行为

应该做什么?

登录成功

实现类设置 remember me cookie (如果设置了对应的 form 参数)

登录失败

如果存在的话,实现类应该删掉这个 cookie

用户退出

如果存在的话,实现类应该删掉这个 cookie

 

知道 RememberMeServices 在何时以及怎样与用户的生命周期关联对于创建自定义的认证处理至关重要,因为我们需要保证任何的自定义认证处理对待 RememberMeServices 保持一致性,以保证这个功能的有效性和安全性。

Remember me 配置指令

可以修改两个常用的配置来改变 remember me 功能的默认行为:

属性

描述

Key

remember mecookie 定义一个唯一的 key 值,以与我们的应用关联

token-validity-seconds

定义时间的长度(以秒计)。 Remember me cookie 将在将被视为认证合法,并且也将用于设置 cookie 的过期时间。

通过对 cookie 哈希内容生成的讲解你可以推断出, Key 属性对与 remember me 功能的安全性很重要。要保证你选择的 key 值是你的应用唯一使用的,并且足够长以至于不能很容易的被猜出。

 

请记住本书的目的何在,我们让 key 的值相对很简单,但是如果你要使用 remember me 功能在你的应用中,建议 key 值包含应用的唯一名称以及至少 36 位长度的随机字符。密码生成工具(在 google 中搜索“ online password generator ”)是一个好办法来得到包含文字数字以及特殊字符组成的伪随机混合内容,以作为你的 remember me key 值。

 

还要记住的是应用处于不同的环境中(如开发、测试、产品级等), remember me cookie 的值也要考虑这些情况。这能够避免 remember me cookie 在测试阶段被无意中的错误使用。

 

一个产品环境的应用中,示例的 key 值如下:

jbcpPets-rmkey-paLLwApsifs24THosE62scabWow78PEaCh99Jus

 

token-validity-seconds 属性被用来设置 remember me token 被接受作为自动登录功能(即使要校验的 token 不合法)的秒数。本属性还会设置用户浏览器中登录 cookie 能够被保存的最长时间。

 

【设置 remember me 的会话 cookie :如果 token-validity-seconds 属性被设置成 -1 ,登录 cookie 将被设置为会话 cookie ,即在用户关闭浏览器后不会被保存。 Token 的有效时间是一个不可配置的值为 2 周(假设用户不关闭浏览器)。不要将这个 cookie 与存储用户的 session ID cookie 相混淆——它们是不同的事情却有着类似的名字。】

 

关于 remember me 功能的高级自定义功能,还有几个其它的配置指令。我们将会在接下来的练习中包含部分,另一部分在第六章:高级配置与扩展 中包含,那时会介绍高级的授权技术。

猜你喜欢

转载自kongcodecenter.iteye.com/blog/1320017