SpringSecurity实现Remember-Me实践

【1】基于会话技术的实现

也就是基于Cookie的实现,用户信息通过某种规则进行加密然后生成一个字符串设置为cookie。

① 登录页面

这里name="remember-me"表示“记住我”的复选框,默认key是remember-me

<form action="/user/login"  method="post">
    <input type="text" name="username" />
    <input type="text" name="password" />
    <input type="checkbox" name="remember-me" />
    <input type="submit" />
</form>

② 配置类开启记住我功能

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private UserDetailsService userDetailsService;


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }
    @Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling().accessDeniedPage("/unauth.html");
        http.formLogin()
                .loginPage("/login.html") //登录页面
                .loginProcessingUrl("/user/login") // 处理登录的请求
                .defaultSuccessUrl("/test/index",true)// 登录成功后跳转路径
                .permitAll();
        http.authorizeRequests()
                .antMatchers("/static/**","/images/**","/css/**","/js/**")//可以直接放行
                .permitAll()
                .antMatchers("/findAll").hasAuthority("admin") // 用户访问findAll 必须有 admin 权限
                .antMatchers("/find").hasAnyAuthority("admin","sale") // 用户访问 find ,拥有admin或者sale之一即可
                .antMatchers("/sale/**").hasRole("sale") // 需要用户具有sale角色
                .antMatchers("/product/**").hasAnyRole("admin","product") //用户具有admin或者product角色之一即可
                .anyRequest().authenticated();//其他请求都需要认证
        http.csrf().disable(); 

		//开启记住我
        http.rememberMe();
    }
}

如下所示,提交表单时请求参数会带上remember-me: on

在这里插入图片描述

提交表单后响应头会设置cookie-remember-me,默认是14天有效期。其值加密规则如下所示:

   username + ":" + expiryTime + ":"
   		+ Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key)

从这个规则也可以看出,如果用户修改了密码那么记住我功能将会自动失效。

得到signatureValue规则如下所示(Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key)):
在这里插入图片描述

得到最终cookie值源码如下:

protected String encodeCookie(String[] cookieTokens) {
  StringBuilder sb = new StringBuilder();

  for(int i = 0; i < cookieTokens.length; ++i) {
      try {
          sb.append(URLEncoder.encode(cookieTokens[i], StandardCharsets.UTF_8.toString()));
      } catch (UnsupportedEncodingException var5) {
          this.logger.error(var5.getMessage(), var5);
      }

      if (i < cookieTokens.length - 1) {
          sb.append(":");
      }
  }

  String value = sb.toString();
  sb = new StringBuilder(new String(Base64.getEncoder().encode(value.getBytes())));

  while(sb.charAt(sb.length() - 1) == '=') {
      sb.deleteCharAt(sb.length() - 1);
  }

  return sb.toString();
}

在这里插入图片描述.

此时关闭浏览器再重新打开,可直接访问受保护的请求(请求头的Cookie会带上remember-me)。

在这里插入图片描述

其本质就是根据某种规则生成一个加密串(串中有用户名和密码)设置为cookie,再次请求时带上该cookie。在autoLogin方法中会解密该cookie,然后根据解密中的用户信息与数据库的数据进行对比来实现自动登录。

原理部分可以查阅一下RememberMeConfigurer、TokenBasedRememberMeServices与AbstractRememberMeServices三个类。

AbstractRememberMeServices关于自动登录的处理逻辑如下:

在这里插入图片描述

这种方式无疑是不安全的,将用户信息通过某种加密规则生成字符串保存到浏览器是有几率被逆向的。故而spring官方推荐使用基于数据库的实现如PersistentTokenBasedRememberMeServices。

【2】基于数据库的实现

AbstractRememberMeServices的另外一个实现是PersistentTokenBasedRememberMeServices,也就是持久化token实现。其核心支撑PersistentTokenRepository又有两个实现:基于内存的InMemoryTokenRepositoryImpl基于数据库的JdbcTokenRepositoryImpl。前者是通过维护了private final Map<String, PersistentRememberMeToken> seriesTokens = new HashMap();这样一个map来实现,后者则依赖于数据库表。

在其源码中可以看到,默认表名与列都已定义persistent_logins (username, series, token, last_used) ,并提供了创建表的策略(如果createTableOnStartup为true)。
在这里插入图片描述

如下所示,注入PersistentTokenRepository 。

@Autowired 
private DataSource dataSource; 

@Bean 
public PersistentTokenRepository persistentTokenRepository(){ 
	JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl(); 
	// 赋值数据源 
	jdbcTokenRepository.setDataSource(dataSource); 
	// 自动创建表,第一次执行会创建,以后要执行就要删除掉! 
	jdbcTokenRepository.setCreateTableOnStartup(true); 
	return jdbcTokenRepository; 
} 

开启记住我功能并设置tokenRepository。

@Autowired 
private PersistentTokenRepository tokenRepository;
// 开启记住我功能 
http.rememberMe() 
	.tokenRepository(tokenRepository) 
	.userDetailsService(usersService);

然后我们可以手动创建表,jdbcTokenRepository.setCreateTableOnStartup(true); 可以注释掉。这里series是用来作为判断、更新用户token的依据,可以理解为userId的作用。

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;

每次自动登录后,会根据series重新生成token并更新:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/32703.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EasyCVR电子地图鼠标悬停展示经纬度的技术实现

EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RTMP、FLV、HLS、WebRTC等格式的视频流。平台可…

VS2019 Python连接Sql server2008

安好后&#xff1a; 测试代码&#xff1a; import pymssqltry:conn pymssql.connect(host127.0.0.1,usersa,password123456,databasehotel,charsetutf8)# 连接并执行Sql语句cursor conn.cursor()sql select * from odercursor.execute(sql)# 获取数据集rs cursor.fetchal…

从操作系统角度了解内存管理

一.内存管理 1.主要功能 内存管理的主要功能有: 内存空间的分配与回收。由操作系统完成主存储器空间的分配和管理&#xff0c;使程序员摆脱存储分配的麻烦&#xff0c;提高编程效率。地址转换。在多道程序环境下&#xff0c;程序中的逻辑地址与内存中的物理地址不可能一致, …

React--Component组件浅析

目录 一 前言二 什么是React组件&#xff1f;三 二种不同 React 组件1 class类组件2 函数组件 四 组件通信方式五 组件的强化方式六 总结 一 前言 在 React 世界里&#xff0c;一切皆组件&#xff0c;我们写的 React 项目全部起源于组件。组件可以分为两类&#xff0c;一类是类…

Redis---集群

目录 一、集群的介绍 1.1 为什么需要集群呢&#xff1f; 1.2 什么是集群&#xff1f; 1.2 集群能干什么呢&#xff1f; 二、集群的算法之分片&槽位slot 2.1 什么是槽位slot&#xff1f; 2.2 分片 2.3 使用槽位和分片的优势 2.4 slot 槽位映射的三种算法 1、哈…

《深入浅出WPF》学习笔记

文章目录 相关资源前言WPF 学习笔记环境配置WPF基础&#xff1a;一个WPF程序是如何启动的xmal文件和cs文件是如何连接的如何确定启动页面xmal文件如何引用别的文件如何引用 WPF是如何创建元素&#xff0c;改变元素的WPF的元素创建和简单属性赋值WPF的树形界面Xmal属性赋值为什么…

内网安全:代理技术详解

目录 代理技术实验所用网络拓扑图及说明 代理技术 SOCK协议 使用代理技术的原因 正向代理与反向代理 实战一&#xff1a;MSF代理通讯 实验原理说明 一. Meterpreter建立路由 二. MSF建立节点 三. 建立代理到MSF上 实战二&#xff1a;CS代理通讯 实验原理说明 一. …

【MYSQL篇】Update语句原理详解

文章目录 前言缓冲池Buffer PoolInnoDB 内存结构redo logundo logBinlog 总结 前言 前面的文章我们已经对MySQL的查询语句的执行流程进行了说明&#xff0c;感兴趣的可以去看看&#xff1a; 【MySQL篇】Select语句原理详解 本篇文章我们来聊聊 MySQL更新语句的执行原理。更新…

从0到1精通自动化测试,pytest自动化测试框架,doctest测试框架(十四)

一、前言 doctest从字面意思上看&#xff0c;那就是文档测试。doctest是python里面自带的一个模块&#xff0c;它实际上是单元测试的一种。 官方解释&#xff1a;doctest 模块会搜索那些看起来像交互式会话的 Python 代码片段&#xff0c;然后尝试执行并验证结果 doctest测试…

spring mvc架构模式概述

三层架构: pojo&#xff0c;bean&#xff0c;domain是一个意思&#xff0c;表示实体类 dao表示操作数据库的那个类&#xff0c;一般是一张表一个

Redis主从架构、数据同步原理、全量同步、增量同步

目录 专栏导读一、Redis主从架构二、数据同步原理三、全量同步的流程三、可以从以下几个方面来优化Redis主从就集群四、全量同步和增量同步区别&#xff1f;五、什么时候执行全量同步&#xff1f;六、什么时候执行增量同步&#xff1f;七、超卖问题 大家好&#xff0c;我是哪吒…

Gitlab保护分支与合并请求

目录 引言 1、成员角色指定 1、保护分支设置 2、合并请求 引言 熟悉了Git工作流之后&#xff0c;有几个重要的分支&#xff0c;如Master(改名为Main)、Develop、Release分支等&#xff0c;是禁止开发成员随意合并和提交的&#xff0c;在此分支上的提交和推送权限仅限项目负责…

机器视觉初步6-1:基于梯度的图像分割

把基于梯度的图像分割单独拿出来。 文章目录 一、图像梯度相关算子的原理1. Sobel算子2. Prewitt算子3. Roberts算子 二、python和halcon算子实现1.python实现2.halcon实现 基于梯度的图像分割方法利用像素之间的梯度信息来进行图像分割。 梯度 1是图像中像素灰度值变化最快的…

Unity Android打包成Apk之后 紫屏 无内容

打包成Apk之后 打开游戏 过完logo是紫色的屏幕什么都没有 解决方法&#xff1a; 打开项目的目录&#xff1a; 删除除了 .vscode assets package 之外的所有文件夹 然后重新打开就可以了

kettle架构图

2、架构说明 1&#xff09;最底层的是kettle的核心引擎层&#xff0c;相关的jar在lib目录下。 2&#xff09;中间是开发层&#xff0c;在开发阶段我们接触最多的就是通过spoon进行开发&#xff0c;通过Spoon.bat或者spoon.sh即可启动客户端&#xff0c;开发文件调试之前要先保…

一篇文章带你从入门都入土 Kafka 消息中间件(原理+代码)

目录 一、Kafka定义 二、消息队列 三、Kafka基础架构图 四、安装Kafka 4.1 为每台服务器下载Kafka并解压 4.2 查看目录结构 4.3 为每台服务器修改配置文件server.properties 4.4 为每台服务器配置Kafka环境变量 4.5 启动zookeeper集群 4.6 启动Kafka集群 4.7 关闭Ka…

河道垃圾自动识别监测算法 opencv

河道垃圾自动识别监测系统通过pythonopencv网络模型技术&#xff0c;河道垃圾自动识别监测算法对水面上的垃圾进行自动识别&#xff0c;一旦发现垃圾污染将自动发出警报。OpenCV基于C实现&#xff0c;同时提供python, Ruby, Matlab等语言的接口。OpenCV-Python是OpenCV的Python…

SpringBoot03:yaml配置注入

目录 一、yaml语法学习 1、配置文件 2、yaml概述 3、yaml基础语法 3.1、字面量&#xff1a;普通的值【数字、布尔值、字符串】 3.2、对象、Map(键值对) 3.3、行内写法&#xff1a; 3.4、数组&#xff08;list、set&#xff09; 二、注入配置文件 1、yaml注入配置文件…

App Inventor 2 语音交互机器人Robot,使用讯飞语音识别引擎

应用介绍 App Inventor 2 语音识别及交互App。识别语言指令并控制机器人运动&#xff0c;主要用到语音识别器及文本朗读器组件&#xff0c;语音识别相关开发最佳入门。代码逻辑简单&#xff0c;App交互性及趣味性非常强~ 视频预览 语音Robot教程&#xff08;难度系数&#xf…

html通过web3JS 获取当前连接的区块链信息和账号信息

前面 我们讲了 MetaMask和ganache的配置安装 并用 MetaMask管理ganache的启动的虚拟区块链 那么 我们现在也完全可以写一个网页来做这个东西的管理 您可以先查看文章web3.js获取导入做一个导入了 web3的html文件 首先我们可以来试着 获取 自己当前是在哪个区块的 getBlockNum…