「这是我参与11月更文挑战的第22天,活动详情查看:2021最后一次更文挑战」
作者:汤圆
个人博客:javalover.cc
前言
前面介绍了基于SpringSecurity的表单登录例子;
本篇介绍怎么给表单登录添加一个记住我的功能;
有了这个功能,那么在token失效后,系统会自动获取最新token,而不用重新登录;
这里需要注意一点:这里的token并不是普通的token,而是JSESSIONID;这个JSESSIONID会在前端第一次请求后端时返回,以后这个JSESSION就是前后台通讯的凭证
目录
- 安全配置
- 前端组件
- 实践-不勾选rememberMe
- 实践-勾选rememberMe
- 更多配置
正文
1. 安全配置
这里我们做一个最简单的配置,如下所示:添加一个rememberMe()方法
@Configuration
@EnableWebSecurity
@Slf4j
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// 数据没有持久化,只是保存在内存中
auth.inMemoryAuthentication()
.withUser("javalover").password(passwordEncoder().encode("123456")).roles("USER")
.and()
.withUser("admin").password(passwordEncoder().encode("123456")).roles("ADMIN");
}
// 授权相关操作
@Override
protected void configure(HttpSecurity http) throws Exception {
log.info("=== SecurityConfiguration.authorize ===");
http
// 登出 所有用户都可以访问
.logout().permitAll()
.deleteCookies("JSESSIONID")
.and()
.rememberMe()
// ...省略其他配置
;
}
}
复制代码
可以看到,我们要做的只是提供一个rememberMe()方法,前台就可以在token失效后自动获取最新的token,而不用再重新输入用户名密码进行登录操作;
2. 前端组件
这里我们前端也尽可能简化,在之前的表单登录基础上,只增加一个复选框 rememberMe,代码如下:
<form action="/login" method="post">
<table>
<tr>
<input name="username" placeholder="用户名">
</tr>
<tr>
<input name="password" placeholder="密码">
</tr>
<tr>
<td>记住我:</td>
<td><input type="checkbox" name="remember-me" /></td>
</tr>
</table>
<button type="submit">登录</button>
</form>
复制代码
3. 实践-不勾选rememberMe
下面我们就可以基于上面的代码,进行一个简单的测试:看一下 勾选rememberMe和不勾选的差别

完整代码见文末地址
第一步:启动程序,界面如下所示:javalover/123456
这里我们先不勾选记住我,点击登录,跳转到如下的主页:
第二步:接下来是重点,这里我们删除本地cookie中的JSESSIONID,如下所示:F12->应用程序->cookies->JSESSION->右键-删除
第三步:刷新页面,可以看到,自动跳转到登录页面,因为token失效了,前后端通讯的凭证没了:
其实上面我们也可以不删除cookie,等着session失效也可以(默认30分钟,可以在application.yml中配置:server.servlet.session.timeout=60,默认单位秒)
后端的session都失效了,那session产生的JSESSIONID肯定也无效了;
4. 实践-勾选rememberMe
下面我们勾选记住我,重复上面的步骤,会发现在删除cookie中的JSESSIONID时,看到多了一个remember-me;
其实这里我们可以换个角度来理解:虽然删了JSESSIONID,但是因为还有一个remember-me,所以前后端的通讯还是没有断开;
所以此时我们刷新页面,还是停留在主页,不会跳转到登录界面;
但是如果我们把remember-me也一起删掉,那么结果很明显,还是会跳到登陆界面。
5. 更多配置
失效时间:
上面我们配置的remember-me,默认的token失效时间是两周,下面我们可以配置的短一点,比如一天:
.logout().permitAll()
.deleteCookies("JSESSIONID")
.and()
.rememberMe()
.tokenValiditySeconds(86400)
.and()
复制代码
失效时间:严格意义上来说,上面这个失效时间 应该是remember-me的失效时间;
这样的话,如果超过一天后,你再去删除JSESSIONID或者session失效,那么刷新页面还是会跳转到登录界面;
加密的密钥:
前面我们在调试界面看到的remember-me cookie值,它的值是由:MD5(用户名+过期时间+密码+密钥)合成的;
这里的密钥我们可以自己配置,如下所示:
.rememberMe()
.key("privateKey")
.tokenValiditySeconds(86400)
复制代码
总结
上面介绍了rememberMe的相关知识,了解了其实rememberMe就是:用新的通讯凭证remember-me
来管理旧的通讯凭证JSESSIONID
;
当JSESSIONID
被删除或者session
过期时,如果rememberMe cookie
还没过期(默认两周),那么系统就可以自动登录
remember-me
真实的过期时间可以在调试界面看到,如下所示: