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