06记住我服务

spring security通过浏览器的用户cookie实现记住我的功能.spring security提供两种记住我的策略.1.基于Token,它依赖加密签名;2.基于持久化,需要数据存储(数据库)


添加依赖

<dependency> 
  <groupId>com.h2database</groupId> 
  <artifactId>h2</artifactId> 
  <version>1.3.163</version> 
  <scope>runtime</scope> 
</dependency>
<dependency> 
  <groupId>org.springframework</groupId> 
  <artifactId>spring-jdbc</artifactId> 
  <version>3.1.0.RELEASE</version>
</dependency> 
<dependency> 
  <groupId>org.springframework</groupId> 
  <artifactId>spring-tx</artifactId> 
  <version>3.1.0.RELEASE</version> 
</dependency>
一.基于Token的记住我实例.
1.配置基于Token的记住我功能.在http的子元素remember-me加入key声明.
<http auto-config="true" use-expressions="true"> 
    ... 
    <remember-me key="jbcpCalendar"/> 
    <logout logout-url="/logout" 
            logout-success-url="/login/form?logout"/> 
</http>

2.修改登录页.加入名为_spring_security_remember_me的字段.
<input type="checkbox" id="remember" name="_spring_security_remember_me" value="true"/>
3.启动jetty测试.登录用户,再关闭浏览器,重新打开页面,查看是否自动登录.顺便使用chrome或firefox查看此cookie.


基于Token的记住我功能是如何起作用的:
记住我的功能在用户的浏览设置了一个base64编码包含以下信息
a.用户名
b.过期日期/时间
c.一个过期日期/时间,用户名,密码, <remember-me>元素的key属性MD5哈希值.
d.组合成单个cookie值在浏览器上以供以后使用.
既然如此,得到了cookie值,采用彩虹表都不那么容易破解了吧.
记住我签名:首先从cookie得到用户名,通过UserDetailsService查询密码,key又能从<remember-me>得到,当然过期日期同样从cookie获取,四样都已知了.将从数据库查出的期望md5哈希与实际md5哈希对比,如果匹配并且没有过期,那就可以允许用户自动登录了.
<remember-me>配置:
key:定义生成remember-me cookie的签名时使用的密钥.确保key是唯一且不易被猜测的.(在google输入online password generator试下吧)
token-validity-seconds:定义的时间长度(单位为秒).验证认证和设置Cookie过期时间戳时用到.
使用完全认证:确保授权访问受保护的资源不仅仅是检查用户的角色,还要使用用户名和密码进行授权.

二.基于持久化的记住我.

1.在数据源加入persistent_logins表:
security-rememberme-schema.sql

create table persistent_logins ( 
    username varchar_ignorecase(100) not null, 
    series varchar(64) primary key, 
    token varchar(64) not null, 
    last_used timestamp not null 
);
<jdbc:embedded-database id="dataSource" type="H2"> 
	... 
	<jdbc:script location="classpath:/database/h2/security-rememberme-schema.sql"/>
</jdbc:embedded-database>

2.配置基于持久化的记住我:在<remember-me>元素,指定data-source-ref属性.

<remember-me key="jbcpCalendar" data-source-ref="dataSource"/> 
3.启动jetty测试.


基于持久化的记住我是如何起作用的?
每个记住我的Cookie包含如下:
Series标识:标识用户的初始化登录,,每一次用户从原来的会话自动登录,它就保持一致。
Token值:当使用持久化的remember-me功能,每次用户授权后都会改变这个值
06记住我服务_第1张图片

当cookie提交时, o.s.s.web.authentication.rememberme.PersistentTokenRepository的实现就会通过Series标识来找出期望的token值和过期时间.
然后将当前实际的token值与期望的token值相比较,如果token值不过期并且相匹配.那么就认为用户通过认证.然后会生成一个同样的Series标识,新的token值,更新过期日期这样的Cookie.
如果tokens值不匹配,就被假定会有人盗用记住我Cookie,此种情况下,spring security将中止记住我这个series(译得特不顺,还是看原文吧),并警告他们登录的用户是受损的.


使用基于基于持久化的记住我的一个好处就是我们能测出记住我cookie是否损坏.正确的series而不正确的token,我们认为是危险的.我们应中断关联的Session.验证是有状态的,我们能中断特定的记住我功能而不必要改变用户的密码.

清理过期的记住我Session:spring security没有提供内置的清理过期记住我session功能,使用spring scheduling是个不错的选择.
记住我与用户的生命周期:
动作 发生了什么? RememberMeServices方法调用
登录成功 实现设置一个记住我的Cookie loginSuccess
登录失败 实现应取消cookie loginFailed
用户注销 实现应取肖cookie logout*
注:login不存在于RememberMeServices接口上,而是每个RememberMeServices的实现还实现了LogoutHandler接口,它就包含了logout方法 .当用户注销时,RememberMeServices的实现可以进行必要的清理.



你可能感兴趣的:(spring,Security)