Spring Security框架下实现两周内自动登录"记住我"功能

本文是Spring Security系列中的一篇。在上一篇文章中,我们通过实现UserDetailsService和UserDetails接口,实现了动态的从数据库加载用户、角色、权限相关信息,从而实现了登录及授权相关的功能。这一节就在此基础上新增,登录过程中经常使用的“记住我”功能,也就是我们经常会在各种网站登陆时见到的"两周内免登录",“三天内免登录”的功能。该功能的作用就是:当我们登录成功之后,一定的周期内当我们再次访问该网站,不需要重新登录。
一、最简实践
其实实现这个功能非常简单,只需要我们在重写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周内免登录。
二、实现原理
很多朋友可能看了上面的实现过程心里都犯懵,这样就实现了?下面和大家说明一下这过程中间,都做了哪些事情。
- 当我们登陆的时候,除了用户名、密码,我们还可以勾选remember-me。
- 如果我们勾选了remember-me,当我们登录成功之后服务端会生成一个Cookie返回给浏览器,这个Cookie的名字默认是remember-me;值是一个token令牌。
- 当我们在有效期内再次访问应用时,经过RememberMeAuthenticationFilter,读取Cookie中的token进行验证。验正通过不需要再次登录就可以进行应用访问。
这个token令牌是一个 MD5 hash字符串:包含username、expirationTime和passwod和一个预定义的key,并将他们经过MD5加密。可能有的朋友会问:这样安全么?如果cookie被劫持,一定是不安全的,别人拿到了这个字符串在有效期内就可以访问你的应用。这就和你的钥匙token被盗了,你家肯定不安全是一个道理。 但是不存在密码被破解为明文的可能性,MD5 hash是不可逆的。

RememberMeAuthenticationFilter在Spring Security过滤器链中处于整体偏后的位置,所以只有当各种传统的登录方式都无法完成验证的情况下,才走RememberMeAuthenticationFilter,这也是符合实际需求的。
三、个性化配置
在实际的开发过程中,我们还可以根据需求做一些个性化的设置,如下:
.rememberMe()
.rememberMeParameter("remember-me-new")
.rememberMeCookieName("remember-me-cookie")
.tokenValiditySeconds(2 * 24 * 60 * 60);
- tokenValiditySeconds用于设置token的有效期,即多长时间内可以免除重复登录,单位是秒。不修改配置情况下默认是2周。
- 通过rememberMeParameter设置from表单“自动登录”勾选框的参数名称。如果这里改了,from表单中checkbox的name属性要对应的更改。如果不设置默认是remember-me。
- rememberMeCookieName设置了保存在浏览器端的cookie的名称,如果不设置默认也是remember-me。如下图中查看浏览器的cookie。

四、token数据库存储方式
上面我们讲的方式,就是最简单的实现“记住我-自动登录”功能的方式。这种方式的缺点在于: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())
期待您的关注
- 向您推荐博主的系列文档:《手摸手教您学习SpringBoot系列-16章97节》
- 本文转载注明出处(必须带连接,不能只转文字):字母哥博客。
Spring Security框架下实现两周内自动登录"记住我"功能的更多相关文章
- JS-两周内自动登录功能
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 在Spring Security框架下JWT的实现细节原理
一.回顾JWT的授权及鉴权流程 在笔者的上一篇文章中,已经为大家介绍了JWT以及其结构及使用方法.其授权与鉴权流程浓缩为以下两句话 授权:使用可信用户信息(用户名密码.短信登录)换取带有签名的JWT令 ...
- Spring Security框架下Restful Token的验证方案
项目使用Restful的规范,权限内容的访问,考虑使用Token验证的权限解决方案. 验证方案(简要概括): 首先,用户需要登陆,成功登陆后返回一个Token串: 然后用户访问有权限的内容时需要上传T ...
- 在Spring Boot框架下使用WebSocket实现聊天功能
上一篇博客我们介绍了在Spring Boot框架下使用WebSocket实现消息推送,消息推送是一对多,服务器发消息发送给所有的浏览器,这次我们来看看如何使用WebSocket实现消息的一对一发送,模 ...
- Spring Security框架中踢人下线技术探索
1.背景 在某次项目的开发中,使用到了Spring Security权限框架进行后端权限开发的权限校验,底层集成Spring Session组件,非常方便的集成Redis进行分布式Session的会话 ...
- Servlet课程0426(十一)Servlet Cookie实现两周内不用重复登录
Welcome.java //登录界面 package com.tsinghua; import javax.servlet.http.*; import java.io.*; import java ...
- 在Spring Boot框架下使用WebSocket实现消息推送
Spring Boot的学习持续进行中.前面两篇博客我们介绍了如何使用Spring Boot容器搭建Web项目(使用Spring Boot开发Web项目)以及怎样为我们的Project添加HTTPS的 ...
- Spring Boot 框架下使用MyBatis访问数据库之基于XML配置的方式
MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML ...
- Spring Security框架进阶、自定义登录
1.Spring Security框架进阶 1.1 Spring Security简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安 ...
随机推荐
- java编写基于netty的RPC框架
一 简单概念 RPC:(Remote Procedure Call),远程调用过程,是通过网络调用远程计算机的进程中某个方法,从而获取到想要的数据,过程如同调用本地的方法一样. 阻塞IO:当阻塞I/O ...
- Computer English Notes
Chapter 1 : About Computer Answer the following - Abbreviation LBS - Location-Based Services HTML - ...
- 使用linq实现回调函数
通过输入的Id找到parentId是该Id的列表,然后找到parentId是上面那个Id的列表,以此类推,找到第一目录下所有子目录的的列表. 通过传入第一目录的Id,得到该目录下的所有子目录. 通过回 ...
- Vue入坑第一篇
写在前面的话:文章是个人学习过程中的总结,为方便以后回头在学习.文章中会参考官方文档和其他的一些文章,示例均为亲自编写和实践,若有写的不对的地方欢迎大家和我一起交流. 一.前言 本篇作为vue入门的一 ...
- Python监控SQL Server数据库服务器磁盘使用情况
本篇博客总结一下Python采集SQL Server数据库服务器的磁盘使用信息,其实这里也是根据需求不断推进演化的一个历程,我们监控服务器的磁盘走了大概这样一个历程: 1:使用SQL Server作业 ...
- 学习笔记57_WCF基础
参考书籍<WCF揭秘> 参考博客园“xfrog” 1.做一个接口,例如: 2.使用一个类,例如:FirstSrvice这个类,来实现这个接口. 3.建立WCF的 宿主 程序: 4.配 ...
- [系列] Go gRPC 调试工具
目录 概述 写一个 gRPC API grpcui 使用 go-gin-api 系列文章 概述 最近这段时间工作挺忙的,发现已经 3 周没更文了... 感谢你们还在,今天给大家分享一款 gRPC 的调 ...
- Java虚拟机之垃圾回收
简述 Java与那些较传统的语言比如C++有个很大不同就是垃圾回收策略了.前者通常是虚拟机自动帮我们做了,而后者就需要我们手动来完成. Java虚拟机帮我们完成了垃圾回收,是不是意味着我们就不用完全去 ...
- STL库学习笔记(一)——什么是STL?
小明是一个很牛逼的程序员,在国际标准化组织工作. 他现在正在设计新一代的C++标准,标准中有一个待实现的函数:findMax(),这个函数要求使用者输入任何类型的数据,他都能找到最大的一个. 于是他想 ...
- jdk 错误1316 指定账户已存在 与 jdk1.7安装和配置环境变量 与 jdk1.8与1.7版本的切换使用
问题: 安装JDK,提示错误信息:,指定的账号已存在. 原因: 安装JDK,相当于安装了一个软件,要使用系统的软件卸载功能卸载,不能只删除安装目录文件夹下的文件,如果只 ...