SpringSecurity5|12.实现RememberMe 及 实现原理分析
security/day08
这个功能大家还熟悉么?我们在登录网站的时候,除了让你输入用户名和密码,还会有个勾选框:
记住我!!!不是让大家记住我哈。

值得一提的是,Spring Security 也提供了这个功能,我们今天就来体验一把。
代码实战
其实想要开启rememberMe功能,其实很简单,只需要简单的修改下配置即可:
@Beanpublic SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests().anyRequest().authenticated().and().formLogin().permitAll().and().rememberMe().and().csrf().disable();return http.build();}
实现思路
- 当用户登录网站后,并且勾选rememberMe
- 服务端认证通过,则把用户信息进行算法加密,加密完成后,通过cookie,让浏览器把cookie保存在本地
- 当浏览器关闭后重新打开网站,浏览器会把cookie带给服务端
- 服务端校验cookie确定用户身份,进而自动登录
源码分析
首先我们找切入点,我们前面讲过当引入一个新功能的时候,必定会引入一个configurer,rememberMe 也不例外:点击.rememberMe()进入源码

看到了RememberMeConfigurer,我们点进去看下主要是看init和configure方法
init
public void init(H http) throws Exception {validateInput();String key = getKey();RememberMeServices rememberMeServices = getRememberMeServices(http, key);http.setSharedObject(RememberMeServices.class, rememberMeServices);LogoutConfigurer<H> logoutConfigurer = http.getConfigurer(LogoutConfigurer.class);if (logoutConfigurer != null && this.logoutHandler != null) {logoutConfigurer.addLogoutHandler(this.logoutHandler);}RememberMeAuthenticationProvider authenticationProvider = new RememberMeAuthenticationProvider(key);authenticationProvider = postProcess(authenticationProvider);http.authenticationProvider(authenticationProvider);initDefaultLoginFilter(http);}
- getKey() 这个就是我们刚开始设置的key,如果不配置,每次系统都会重启,导致需要重新登录
- getRememberMeServices() 用来实现自动登录、处理登录成功和登录失败的逻辑,主要有两个继承
- PersistentTokenBasedRememberMeServices 持久化令牌到数据库
- TokenBasedRememberMeServices
- http.authenticationProvider(authenticationProvider);创建一个认证器放到providerList里面
- initDefaultLoginFilter(http); 在自定生成登录页面加上rememberMe 选框
configure
public void configure(H http) {RememberMeAuthenticationFilter rememberMeFilter = new RememberMeAuthenticationFilter(http.getSharedObject(AuthenticationManager.class), this.rememberMeServices);if (this.authenticationSuccessHandler != null) {rememberMeFilter.setAuthenticationSuccessHandler(this.authenticationSuccessHandler);}rememberMeFilter = postProcess(rememberMeFilter);http.addFilter(rememberMeFilter);}
- 创建了一个过滤器:RememberMeAuthenticationFilter
- postProcess(rememberMeFilter); 注入IOC容器
- 在http中加入rememberMe过滤器
看完了RememberMeConfigurer的两个核心方法之后,我们现在知道容器中已经有了RememberMeAuthenticationFilter和RememberMeAuthenticationProvider
现在分别来看下
RememberMeAuthenticationFilter
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws IOException, ServletException {Authentication rememberMeAuth = this.rememberMeServices.autoLogin(request, response);if (rememberMeAuth != null) {// Attempt authenticaton via AuthenticationManagertry {rememberMeAuth = this.authenticationManager.authenticate(rememberMeAuth);// Store to SecurityContextHolderSecurityContext context = SecurityContextHolder.createEmptyContext();context.setAuthentication(rememberMeAuth);SecurityContextHolder.setContext(context);onSuccessfulAuthentication(request, response, rememberMeAuth);this.securityContextRepository.saveContext(context, request, response);if (this.successHandler != null) {this.successHandler.onAuthenticationSuccess(request, response, rememberMeAuth);return;}}catch (AuthenticationException ex) {this.rememberMeServices.loginFail(request, response);onUnsuccessfulAuthentication(request, response, ex);}}chain.doFilter(request, response);}
- 调用autoLogin方法
- 从cookie提取用户身份,在调用loadUserByUsername获取用户详细信息
- 校验用户身份是否合法(根据不同的令牌存储方式进行不同校验)
- 如果校验通过,则返回Authentication(RememberMeAuthenticationToken)
- authenticate
- 如果autoLogin成功,则和前面普通登录一样进行认证
- 因为这里生成的是RememberMeAuthenticationToken,则最终会被RememberMeAuthenticationProvider处理
- 如果认证返回则进行对应的响应处理
RememberMeAuthenticationProvider
public Authentication authenticate(Authentication authentication) throws AuthenticationException {if (!supports(authentication.getClass())) {return null;}if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication).getKeyHash()) {throw new BadCredentialsException(this.messages.getMessage("RememberMeAuthenticationProvider.incorrectKey","The presented RememberMeAuthenticationToken does not contain the expected key"));}return authentication;}
这里的逻辑只做了一步,校验key的hashCode是否一致,如果一致,则校验通过
相关文章:
SpringSecurity5|12.实现RememberMe 及 实现原理分析
security/day08 这个功能大家还熟悉么?我们在登录网站的时候,除了让你输入用户名和密码,还会有个勾选框: 记住我!!!不是让大家记住我哈。 值得一提的是,Spring Security 也提供了这个…...
持续集成交付CICD:Jenkins Sharedlibrary 共享库
目录 一、理论 1.共享库 2.共享库配置 3.使用共享库 4.共享库扩展 二、实验 1.连接共享库 2.使用共享库 三、问题 1.路径报错 2.readJSON 报错 一、理论 1.共享库 (1)概念 1)共享库这并不是一个全新的概念,其实在编…...
Linux--网络编程
一、网络编程概述1.进程间通信: 1)进程间通信的方式有**:管道,消息队列,共享内存,信号,信号量这么集中 2)特点:依赖于linux内核,基本是通过内核来实现应用层…...
数据结构 并查集
作用 快速的处理以下问题:【近乎O(1)的时间完成】 1.将两个集合合并 2.询问两个元素是否在一个集合中 用树的形式维护集合 基本原理 每一个集合用一棵树表示 每一个集合的编号就是根结点的编号,对于每一个结点,都存储其父结点…...
算法通关村第十六关黄金挑战——求滑动窗口中的最大值(滑动窗口与堆方法、双端队列法和直接比较法)
大家好,我是怒码少年小码。 今天这篇就讲一道题目,不难😎,但是一定要学会自己思考。 滑动窗口最大值 LeetCode 239:给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。…...
常见树种(贵州省):009楠木、樟木、桂木种类
摘要:本专栏树种介绍图片来源于PPBC中国植物图像库(下附网址),本文整理仅做交流学习使用,同时便于查找,如有侵权请联系删除。 图片网址:PPBC中国植物图像库——最大的植物分类图片库 一、楠木 …...
全志H616开发版
开发板介绍: 二、开发板刷机 SDFormatter TF卡的格式化工具、Win32Diskimager 刷机工具 刷机镜像为:Orangepizero2_2.2.0_ubuntu_bionic_desktop_linux4.9.170.img 使用MobaXterm_Personal_20.3连接使用 网络配置:nmcli dev wifi 命令接入网…...
【Spring boot】RedisTemplate中String、Hash、List设置过期时间
文章目录 前言Redis中String设置时间的方法Redis中Hash和List设置时间的方法Redis中Hash的put、putAll、putIfAbsent区别 前言 时间类型:TimeUnit import java.util.concurrent.TimeUnit;TimeUnit.SECONDS:秒 TimeUnit.MINUTES:分 TimeUnit.HOURS&…...
Nosql之redis概述及基本操作
关系数据库与非关系型数据库概述 关系型数据库 关系型数据库是一个结构化的数据库,创建在关系模型(二维表格模型)基础上,一般面向于记录。SQL语句(标准数据查询语言)就是一种基于关系型数据库的语言,用于执行对关系型…...
使ros1和ros2的bag一直互通
很多文章都是先source ros1 然后source ros2,再play bag source /opt/ros/noetic/setup.bash source /opt/ros/foxy/setup.bash ros2 bag play -s rosbag_v2 kitti_raw00.bag 但实测会出问题: 为使ros1和ros2的bag一直互通 sudo apt update sudo apt install ros-foxy-ro…...
【正点原子 linux 驱动编程】
在此声明,正用点编的说明书真的拉,丝毫不具备兼容性。。比如linux的第一个实验,其中包含的 unregister_chrdev_region 函数,fileoperation 结构体等均来自 <linux/fs.h> 文件,搞不懂,他们方ide.h&…...
使用Python的turtle模块绘制玫瑰花图案(含详细Python代码与注释)
1.1引言 turtle模块是Python的标准库之一,它提供了一个绘图板,让我们可以在屏幕上绘制各种图形。通过使用turtle,我们可以创建花朵、叶子、复杂的图案等等。本博客将介绍如何使用turtle模块实现绘制图形的过程,并展示最终结果。 …...
Redis学习笔记14:基于spring data redis及lua脚本ZSET有序集合实现环形结构案例及lua脚本如何发送到redis服务器
案例实现目标,一、实现一个环形结构,环形结构上节点有一个阀值threshold,超过阀值则移除分数score最低的成员,不足则将当前成员添加进环中,且确保成员不可重复;二、每次访问环中的数据都需要刷新key的过期时间…...
openssl C++研发之pem格式处理详解
一、PEM_writeXXX和EM_write_bio_XXX 在OpenSSL的crypto/pem.h头文件中,PEM_write_XXXX和PEM_write_bio_XXXX系列函数用于将特定类型的数据写入文件或BIO(内存缓冲区)中,其中XXXX代表不同的数据类型。 这些函数的使用方式相似&a…...
【教3妹学编辑-mysql】详解数据库三大范式
什么是范式 简单地理解就是:数据库设计时遵循的规范 三大范式 数据库三大范式包含:1、第一范式(1NF);2、第二范式(2NF);3、第三范式(3NF)。其中,第一范式(1NF)的要求是属性不可分割,第二范式(2NF)的要求是…...
【计算机网络笔记】路由算法之链路状态路由算法
系列文章目录 什么是计算机网络? 什么是网络协议? 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能(1)——速率、带宽、延迟 计算机网络性能(2)…...
读像火箭科学家一样思考笔记04_第一性原理(下)
1. 来自无形规则的阻力 1.1. 无形规则 1.1.1. 僵化成规则的不必要习惯和行为 1.1.2. 不像有形的书面规则 1.1.2.1. 书面规则出现在标准操作流程中,可以修改或删除 1.1.3. 成文的规则可能会抗拒变革,但无形规则却更加顽固 1.1.4. 我们为强加在自己身…...
开源集群管理系统对比分析:Kubernetes 与 Apache Mesos
集群管理系统是关键的软件解决方案,可以在互连机器网络中有效分配和利用计算资源。毫无疑问,它们通过确保可扩展性、高可用性和有效的资源管理在现代计算中发挥着至关重要的作用,这使得它们对于运行复杂的应用程序、管理数据中心以及进一步增…...
matlab 坡度滤波算法地面分割
目录 一、算法原理1、实现流程2、参考文献二、代码实现三、结果展示四、测试数据一、算法原理 1、实现流程 1、格网示意图 2、计算格网行列数 公式中的特殊符号为向上取整,...
【腾讯云 HAI域探秘】高性能服务器引领AI革新浪潮:从AI绘画、知识问答到PyTorch图像分类、视频检测的全方位探索
目录 1 HAI(高性能应用服务)简介2 HAI的应用场景2.1 HAI在AI作画中的灵活性与效率2.2 深入探索LLM语言模型的应用与性能2.3 HAI支持的AI模型开发环境与工具 3 基于stable difussio的AI 绘画应用实践3.1 使用AI模型中的stable diffusion模型服务3.2 设置和…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
Windows电脑能装鸿蒙吗_Windows电脑体验鸿蒙电脑操作系统教程
鸿蒙电脑版操作系统来了,很多小伙伴想体验鸿蒙电脑版操作系统,可惜,鸿蒙系统并不支持你正在使用的传统的电脑来安装。不过可以通过可以使用华为官方提供的虚拟机,来体验大家心心念念的鸿蒙系统啦!注意:虚拟…...
归并排序:分治思想的高效排序
目录 基本原理 流程图解 实现方法 递归实现 非递归实现 演示过程 时间复杂度 基本原理 归并排序(Merge Sort)是一种基于分治思想的排序算法,由约翰冯诺伊曼在1945年提出。其核心思想包括: 分割(Divide):将待排序数组递归地分成两个子…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
