在我们登录一些网站的时候,通常会有一个选项-记住我。选中该选项,登录成功后,无论浏览器关闭,还是服务重启,只要不清除浏览器缓存信息,且Cookie在网站预设的有效期时间内,则无需重新登录网站即可访问其资源。
其实,Spring Security 框架也可以实现相同的功能。本文便基于 Spring Security 框架默认的用户名密码登录为基础,为其添加 RememberMe(记住我)选项。
首先,修改登录页面,将 记住我 复选框 name 属性修改为 remember-me。
<form th:action="@{/login}" method="post" th:method="post" class="mt-1">
......
<div class="checkbox">
<label><input type="checkbox" name="remember-me"> 记住我</label>
</div>
......
</form>
为何要修改 name 属性修改为 remember-me,而不是别的什么名字呢?其实,原因并不复杂,简单点来说,这是 Spring Security 框架默认的 记住我 复选框的名称。当然,你也可以命名为别的名字,然后把相关配置也同样修改为此名字即可。
还记得 UsernamePasswordAuthenticationFilter 类有一个 rememberMeServices 属性吗?初始值为 NullRememberMeServices。
private RememberMeServices rememberMeServices = new NullRememberMeServices();
在身份认证成功后,会执行 successfulAuthentication 方法。这在文章史上最简单的Spring Security教程(二十五):UsernamePasswordAuthenFilter详解中也有提及,不过并没有过多的解释。此方法执行过程中,便会调用 RememberMeServices 接口的 loginSuccess 方法。
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response, FilterChain chain, Authentication authResult)
throws IOException, ServletException {
if (logger.isDebugEnabled()) {
logger.debug("Authentication success. Updating SecurityContextHolder to contain: "
+ authResult);
}
SecurityContextHolder.getContext().setAuthentication(authResult);
rememberMeServices.loginSuccess(request, response, authResult);
// Fire event
if (this.eventPublisher != null) {
eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
authResult, this.getClass()));
}
successHandler.onAuthenticationSuccess(request, response, authResult);
}
RememberMeServices 接口的 loginSuccess 便会判断登录页的 记住我 复选框是否选中,选中的情况下,才会执行后续逻辑。
public final void loginSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication successfulAuthentication) {
if (!rememberMeRequested(request, parameter)) {
logger.debug("Remember-me login not requested.");
return;
}
onLoginSuccess(request, response, successfulAuthentication);
}
注意,这是 RememberMeServices 接口的 抽象实现类 AbstractRememberMeServices 中的实现逻辑,由于 UsernamePasswordAuthenticationFilter 类 rememberMeServices 属性的初始值为 NullRememberMeServices,其并没有继承 AbstractRememberMeServices 类,只是空的实现。因此,需要配置 UsernamePasswordAuthenticationFilter 类中的 rememberMeServices 属性为具体的 RememberMeServices 接口实现。
然后,调整一下 Spring Security 配置,新增 rememberMe 的相关配置。
protected void configure(HttpSecurity http) throws Exception {
http
......
.rememberMe()
.userDetailsService(userDetailsService())
.tokenValiditySeconds(14 * 24 * 60 * 60)
......
}
token默认有效期为两周,即14天,与 Spring Security 默认配置相同。
万事俱备,启动系统,访问登录页面,尝试一下。
输入用户名、密码,最重要的不要忘了,勾选 记住我 选项,系统正常调转到了系统首页。
关闭浏览器,直接访问系统首页,此时,仍然可以直接访问,并没有重定向到登录页,无需输入用户名、密码。相同的,重启应用之后,同样可以直接访问系统首页,也无需再次登录。
记住我 改造完成。
其它详细源码,请参考文末源码链接,可自行下载后阅读。
我是银河架构师,十年饮冰,难凉热血,愿历尽千帆,归来仍是少年!
如果文章对您有帮助,请举起您的小手,轻轻【三连】,这将是笔者持续创作的动力源泉。当然,如果文章有错误,或者您有任何的意见或建议,请留言。感谢您的阅读!
源码
github
https://github.com/liuminglei/SpringSecurityLearning/tree/master/31
gitee
https://gitee.com/xbd521/SpringSecurityLearning/tree/master/31
如果喜欢我们的文章
可以关注我们
也可以点击右下角的在看告诉我们
期待与您相遇