本文是Spring Security系列中的一篇。在上一篇文章中,咱们经过实现UserDetailsService和UserDetails接口,实现了动态的从数据库加载用户、角色、权限相关信息,从而实现了登陆及受权相关的功能。这一节就在此基础上新增,登陆过程当中常用的“记住我”功能,也就是咱们常常会在各类网站登录时见到的"两周内免登陆",“三天内免登陆”的功能。该功能的做用就是:当咱们登陆成功以后,必定的周期内当咱们再次访问该网站,不须要从新登陆。spring
其实实现这个功能很是简单,只须要咱们在重写WebSecurityConfigurerAdapter 方法配置HttpSecurity 的时候增长rememberMe()方法。(下面代码中省略了大量的关于Spring Security登陆验证的配置,在本号此前的文章中已经讲过)数据库
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.rememberMe(); //实现记住我自动登陆配置,核心的代码只有这一行 } }
而后在登陆表单中加入一个checkbox勾选框,name属性的值目前必须是“remember-me”(个性化更改的方法后面会讲)。浏览器
<label><input type="checkbox" name="remember-me">自动登陆</label>
就是这么简单,咱们就实现了记住我功能,默认效果是:2周内免登陆。安全
不少朋友可能看了上面的实现过程内心都犯懵,这样就实现了?下面和你们说明一下这过程当中间,都作了哪些事情。springboot
这个token令牌是一个 MD5 hash字符串:包含username、expirationTime和passwod和一个预约义的key,并将他们通过MD5加密。可能有的朋友会问:这样安全么?若是cookie被劫持,必定是不安全的,别人拿到了这个字符串在有效期内就能够访问你的应用。这就和你的钥匙token被盗了,你家确定不安全是一个道理。 可是不存在密码被破解为明文的可能性,MD5 hash是不可逆的。cookie
RememberMeAuthenticationFilter在Spring Security过滤器链中处于总体偏后的位置,因此只有当各类传统的登陆方式都没法完成验证的状况下,才走RememberMeAuthenticationFilter,这也是符合实际需求的。app
在实际的开发过程当中,咱们还能够根据需求作一些个性化的设置,以下:ide
.rememberMe() .rememberMeParameter("remember-me-new") .rememberMeCookieName("remember-me-cookie") .tokenValiditySeconds(2 * 24 * 60 * 60);
上面咱们讲的方式,就是最简单的实现“记住我-自动登陆”功能的方式。这种方式的缺点在于:token与用户的对应关系是在内存中存储的,当咱们重启应用以后全部的token都将消失,即:全部的用户必须从新登录。为此,Spring Security还给咱们提供了一种将token存储到数据库中的方式,重启应用也不受影响。学习
> 有的文章说使用数据库存储方式是由于这种方式更安全,笔者不这么认为。虽然数据库存储的token的确再也不是用户名、密码MD5加密字符串了,而是一个随机序列号。可是一旦你的随机序列号cookie被劫持,效果是同样的。比如你家有把密码锁:你把钥匙丢了和你把密码丢了,危害性是同样的。网站
上图是token数据库存储方式的实现原理和验证过程,下面咱们就来实现一下。首先,咱们须要键一张数据库表persistent_logins:
CREATE TABLE `persistent_logins` ( `username` varchar(64) NOT NULL, `series` varchar(64) NOT NULL, `token` varchar(64) NOT NULL, `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`series`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
初始化一个PersistentTokenRepository类型的Spring bean,并将系统使用的DataSource注入到该bean中。(固然前提必定是你已经在Spring Boot的application.yml中配置好DataSource相关的链接属性,这里再也不赘述)
@Autowired private DataSource dataSource; @Bean public PersistentTokenRepository persistentTokenRepository(){ JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl(); tokenRepository.setDataSource(dataSource); return tokenRepository; }
最后在Spring Security配置方法configure(HttpSecurity http)加上以下的个性化配置:
.rememberMe() .tokenRepository(persistentTokenRepository())