述
一个网站往往是登录一次之后,一周内或者一月内都不需要重新登录, 这里就是用到了记住我的功能,不管是浏览器关闭,或者是我们服务端的服务重启,都没有关系,用户都不需要重新去登录, 下面看一下如何去实现这个功能
原理简介
如下图:
先来简单的看一下这个流程
- 用户的认证请求过来之后,首先会进入到
UsernamePasswordAuthenticationFilter
这个过滤器 - 认证成功之后, 调用
RemeberMeService
根据用户名去生成一个Token - 生成Token之后,由指定的
TokenRepository
去把Token写到DB中去,同时写到浏览器的Cookie中 - Cookie和DB中有了token之后,当用户再次登录系统,就会经过
RememberMeAuthenticationFilter
从Cookie中读取Token,然后RemeberMeService
去DB里面去查询,如果有记录会调用UserDetailsService
然后根据用户名与密码生成认证的信息
RememberMeAuthenticationFilter
这个过滤器的位置如图:
代码实现
前端配置
原理大致了解了之后,看一下我们的项目中应该如何实现
首先,登录页面需要一个复选框 type 是 checkbox, 然后 name 必须是 remember-me,这个是写死的 ,如下:1
<input type="checkbox" class="checkbox" name="remember-me" >
DB配置
这里的token是放到DB里面的,所以我们还需要在数据库中建一个表,sql如下:1
2
3
4
5
6CREATE TABLE persistent_logins (
username VARCHAR (64) NOT NULL,
series VARCHAR (64) PRIMARY KEY,
token VARCHAR (64) NOT NULL,
last_used TIMESTAMP NOT NULL
);
代码中的配置
在 BrowserSecurityConfig
中需要做出以下配置
1 | @Autowired |
.tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())
这个配置是配置过期秒数, 然后这里需要在浏览器的配置类中加一个属性,如下:
1 | /** |
到这里配置就完成了, 可以运行项目试一下效果
源码分析
RememberMeAuthenticationFilter
这个过滤器是在 UsernamePasswordAuthenticationFilter
后面的, 也就是说只有登录认证成功之后,才会去做记住我的功能
所以这里先看一下认证成功之后,调用的方法,就是 AbstractAuthenticationProcessingFilter
里面的 successfulAuthentication()
方法
如上图,首次登录成功之后,会调用 rememberMeServices.loginSuccess(request, response, authResult);
点进去看一下
这一步主要就是生产token,分别写到数据库和浏览器的cookie中去
然后看一下下一次登录进来的流程, 首先会进到 RememberMeAuthenticationFilter
中, 然后看一下他的方法
这里主要调用了 rememberMeServices.autoLogin(request, response);
这个自动登录的方法,然后看一下这个方法里面
这里先是从cookie中组装了一个 UserDetails
对象出来,然后check一次, 最后返回认证对象
总结
用户首次登录成功之后,生成一个token,分别放到数据库和浏览器的cookie中去
第二次登录认证,先判断此次登录是否有经过认证(从session中找),没有的话,调用自动登录, 然后从cookie中拿token, 通过和数据库中的比对, 组合一个 UserDetails
, 然后检查返回,最后放到session中去