在我们登录一些网站的时候,通常会有一个选项-记住我。选中该选项,登录成功后,无论浏览器关闭,还是服务重启,只要不清除浏览器缓存信息,且Cookie在网站预设的有效期时间内,则无需重新登录网站即可访问其资源。

其实,Spring Security 框架也可以实现相同的功能。本文便基于 Spring Security 框架默认的用户名密码登录为基础,为其添加 RememberMe(记住我)选项。

首先,修改登录页面,将 记住我 复选框 name 属性修改为 remember-me。

"@{/login}" method=  ......

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();
private RememberMeServices rememberMeServices = new NullRememberMeServices();

在身份认证成功后,会执行 successfulAuthentication 方法。这在文章史上最简单的Spring Security教程(二十五):UsernamePasswordAuthenticationFilter详解中也有提及,不过并没有过多的解释。此方法执行过程中,便会调用 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);}
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);}
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)        ......}
protected void configure(HttpSecurity http) throws Exception {    http        ......        .rememberMe()        .userDetailsService(userDetailsService())        .tokenValiditySeconds(14 * 24 * 60 * 60)        ......}

token默认有效期为两周,即14天,与 Spring Security 默认配置相同。万事俱备,启动系统,访问登录页面,尝试一下。

springsecurity设置密码不加密 springsecurity默认用户名密码_JAVA

输入用户名、密码,最重要的不要忘了,勾选 记住我 选项,系统正常调转到了系统首页。

springsecurity设置密码不加密 springsecurity默认用户名密码_复选框_02

关闭浏览器,直接访问系统首页,此时,仍然可以直接访问,并没有重定向到登录页,无需输入用户名、密码。相同的,重启应用之后,同样可以直接访问系统首页,也无需输入用户名、密码。记住我 改造完成。其它详细源码,请参考文末源码链接,可自行下载后阅读。

当然,如果文章有错误,或者您有任何的意见或建议,请留言。感谢您的阅读!源码githubhttps://github.com/liuminglei/SpringSecurityLearning/tree/master/31gitee

https://gitee.com/xbd521/SpringSecurityLearning/tree/master/31