【SpringBoot】Redis集中管理Session和自定义用户参数解决登录状态及校验问题
《RabbitMQ》《Spring》《SpringMVC》
文章目录
- 前言
- 一、分布式Session问题
- Redis集中管理Session
- 二、用户校验问题
- 自定义用户参数
- MVC拦截器
- 总结
前言
主要讲解:Redis集中管理Session存储用户登录信息,解决分布式Session问题;自定义用户参数配合MVC拦截器实现控制层入参前进行用户校验,解决每层用户接口都要做用户校验问题。
一、分布式Session问题
在实现用户登录时,我们需要注意的就是就是用户权限带来的用户登录状态问题:在大多数项目中,应用采用Nginx反向代理,这会存在一种情况——用户信息在Tomcat1登录之后,用户信息放在Tomcat1的Session里,过一会,请求又被Nginx分发到Tomcat2上,这是Tomcat2上Session里还没有用户信息,于是又要登录。
解决方案有很多:
- Session复制
- 优点
- 无需修改代码,只需要修改Tomcat配置
- 缺点
- Session同步传输占用内网带宽
- 多台Tomcat同步性能指数级下降
- Session占用内存,无法有效水平扩展
- 优点
- 前端存储
- 优点
- 不占用服务器端内存
- 缺点
- 存在安全风险
- 数据大小受到cookie限制
- 占用外网带宽
- 优点
- Session粘滞
- 优点
- 无需修改代码
- 服务器端可以水平扩展
- 缺点
- 增加新机器,会重新Hash,导致重新登录
- 应用重启,需要重新登录
- 优点
Redis集中管理Session
- 这里采用Redis集中管理所有Session,即多个地方从一个地方(Redis)中获取信息。当然大家也可以使用SpringSession实现分布式Session。
- 实现:登录时将用户信息存入Redis,这里只是实现了简单的集中储存用户信息,并没有
- 对于Redis集中管理Session,我在做黑马点评时记录过,很完善,可以看看:短信登录实现(黑马点评)
Redis配置类:键值对序列化
/*** @Version: 1.0.0* @Author: Dragon_王* @ClassName: RedisConfig* @Description: Redis配置类* @Date: 2024/1/25 15:32*/
@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();//key序列化redisTemplate.setKeySerializer(new StringRedisSerializer());//value序列化redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());//hash的key序列化redisTemplate.setHashKeySerializer(new StringRedisSerializer());//hash的value序列化redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());//注入连接工厂redisTemplate.setConnectionFactory(redisConnectionFactory);return redisTemplate;}
}
登录逻辑:
/*** @Version: 1.0.0* @Author: Dragon_王* @ClassName: IUserServiceImpl* @Description: 登录处理* @Date: 2024/1/23 15:52*/
@Service
@Primary
public class IUserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate RedisTemplate redisTemplate;/**** @Description: 登录* @param loginVo* @methodName: doLogin* @return: com.example.seckill.vo.RespBean* @Author: dragon_王* @Date: 2024-01-23 17:38:35*/@Overridepublic RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {String mobile = loginVo.getMobile();String password = loginVo.getPassword();//根据手机号获取用户User user = userMapper.selectById(mobile);if (null == user) {throw new GlobalException(RespBeanEnum.LOGIN_ERROR);}//判断密码是否正确if (!MD5Util.formPassToDBPass(password,user.getSalt()).equals(user.getPassword())){throw new GlobalException(RespBeanEnum.LOGIN_ERROR);}//生成cookieString ticket = UUIDUtil.uuid();redisTemplate.opsForValue().set("user:" + ticket,user);CookieUtil.setCookie(request,response,"userTicker",ticket);return RespBean.success();}/**** @Description: 根据cookie获取用户* @param userTicker* @methodName: getUserByCookie* @return: com.example.seckill.pojo.User* @Author: dragon_王* @Date: 2024-01-25 16:03:14*/@Overridepublic User getUserByCookie(String userTicker,HttpServletRequest request,HttpServletResponse response) {if (StringUtils.isEmpty(userTicker)){return null;}User user = (User) redisTemplate.opsForValue().get("user:" + userTicker);if (user != null) {CookieUtil.setCookie(request,response,"userTicker",userTicker);}return user;}
}
主要看如下代码:
//在账号密码正确后随机生成UUID,将 “user”+UUID 作为用户信息唯一key值,并存入redis中,这里我的cookie里存了一份UUID,因为Cookie存在于服务器或本地,不同于Session(只能存在于服务器),在使用应用程序时,不管请求在哪个tomcat,而用户在自己浏览器或本地上的信息能获取到。CookieUtil是自定义封装的cookie存取的工具类。String ticket = UUIDUtil.uuid();redisTemplate.opsForValue().set("user:" + ticket,user);CookieUtil.setCookie(request,response,"userTicker",ticket);return RespBean.success();//如果Cookie里没有就说明用户没登陆过,因为我在登录时已经存过当前用户随机生成的UUID作为Cookie,没有的话就会返回空,有就根据当前用户UUID获取存在redis中的序列化的用户信息public User getUserByCookie(String userTicker,HttpServletRequest request,HttpServletResponse response) {if (StringUtils.isEmpty(userTicker)){return null;}User user = (User) redisTemplate.opsForValue().get("user:" + userTicker);if (user != null) {CookieUtil.setCookie(request,response,"userTicker",userTicker);}return user;}
在黑马点评实现登录时,关于分布式Session,用到了token刷新:就是在用户登录时将用户信息存储到redis中,所谓token值,使用的就是UUID,同时token也作为redis中的key值,并且设置过期时间,但是这里有个刷新机制,就是设置拦截器——当用户访问某个页面时就自动刷新过期时间,使得如果用户一直在操作就不会突然过期,详细看那篇文章,这里不再补充。
二、用户校验问题
对于用户操作,会有权限限制即判断用户是否登录,如果每层用户业务接口都做用户校验会太过麻烦,所以可以自定义用户参数,在每次controller层入参之前就去做拦截校验。
自定义用户参数
/*** @Version: 1.0.0* @Author: Dragon_王* @ClassName: UserArgumentResolve* @Description: 自定义用户参数* 获取用户是否登录* @Date: 2024/1/25 16:31*/
@Component
public class UserArgumentResolve implements HandlerMethodArgumentResolver {@Autowiredprivate IUserService userService;@Overridepublic boolean supportsParameter(MethodParameter parameter) {Class<?> parameterType = parameter.getParameterType();return parameterType == User.class;}@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);HttpServletResponse response = webRequest.getNativeRequest(HttpServletResponse.class);String ticker = CookieUtil.getCookieValue(request, "userTicker");if (StringUtils.isEmpty(ticker)){return null;}return userService.getUserByCookie(ticker,request,response);}
}
解释:supportsParameter函数判断参数类型是否为User类型,是的的话执行resolveArgument函数,resolveArgument函数则会先查询当前cookie里是否有用户信息,没有的话返回空,有的话返回用户通过校验。
MVC拦截器
/*** @Version: 1.0.0* @Author: Dragon_王* @ClassName: WebConfig* @Description: MVC配置类* @Date: 2024/1/25 16:27*/
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {@Autowiredprivate UserArgumentResolve userArgumentResolve;@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {resolvers.add(userArgumentResolve);}
}
这样设置后,以后Controller层接口传参只需要有User类型对象,自动校验用户状态,判断用户是否属于登录状态。
总结
以上就是Redis集中管理Session存储用户登录信息,解决分布式Session问题;自定义用户参数配合MVC拦截器实现控制层入参前进行用户校验,解决每层用户接口都要做用户校验问题的讲解。
相关文章:

【SpringBoot】Redis集中管理Session和自定义用户参数解决登录状态及校验问题
🏡浩泽学编程:个人主页 🔥 推荐专栏:《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》 🛸学无止境,不骄不躁,知行合一 文章目录 前言一、分布…...
【0256】揭晓pg内核中MyBackendId的分配机制(后端进程Id,BackendId)(二)
上一篇:【0255】揭晓pg内核中MyBackendId的分配机制(后端进程Id,BackendId)(一) 文章目录 1. 前言2. 分配BackendId2.1 何时为backend process分配BackendId2.1.1 找出未使用的slot(inactive slot)2.3 BackendId序号从多少开始?2.4 后端进程退出后,其BackendId被释放…...
eclipse4.28.0版本如何安装FatJar插件
场景: 今天准备温故下以前的老项目,于是下载了最新版本的Eclipse IDE for Enterprise Java and Web Developers - 2023-06,老项目中有些需要将程序打成jar包,于是考虑安装FatJar插件。 问题描述 一顿操作后,发现FatJar死活安装了,在线安装提示content.xml异常;离线安装…...

查大数据检测到风险等级太高是怎么回事?
随着金融风控越来越多元化,大数据作为新兴的技术被运用到贷前风控中去了,不少人也了解过自己的大数据,但是由于相关知识不足,看不懂报告,在常见的问题中,大数据检测到风险等级太高是怎么回事呢?小易大数据…...

Leetcode 30天高效刷数据结构和算法 Day1 两数之和 —— 无序数组
两数之和 —— 无序数组 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现…...
Hair Tool for Blender3D
CGer.com - Hair Tool for Blender3D - CGer资源网 Hair Tool 1.5 for Blender3D 链接: https://pan.baidu.com/s/1kVABn6n 密码: gwprHair Tool 1.65-1.8 for Blender链接: https://pan.baidu.com/s/1A7cW_Ms2baGQ2M0iE1dQhQ 密码: 81bqHair Tool for Blender 1.9.2链接: http…...

【最详解】如何进行点云的凹凸缺陷检测(opene3D)(完成度80%)
文章目录 前言实现思路想法1想法2想法3 补充实现想法1想法2代码 想法3代码 总结 前言 读前须知: 首先我们得确保你已经完全知晓相关的基本的数学知识,其中包括用最小二乘法拟合曲二次曲面,以及曲面的曲率详细求解。若还是没弄清楚࿰…...

海外云手机——平台引流的重要媒介
随着互联网的飞速发展,跨境电商、短视频引流以及游戏行业等领域正经历着迅猛的更新换代。在这个信息爆炸的时代,流量成为至关重要的资源,而其中引流环节更是关乎业务成功的关键。海外云手机崭露头角,成为这一传播过程中的重要媒介…...
数据库-计算机三级学习记录-4DBAS功能概要设计
DBAS功能概要设计 参照b站【计算机三级数据库技术】 DBAS功能设计包括应用软件中的数据库事务设计和应用程序设计。 功能设计过程一般被划分为总体设计、概要设计和详细设计。而具体到数据库事务设计部分,又可分成事务概要设计和事务详细设计。完成系统设计工作之后…...

JVM-虚拟机栈
虚拟机栈 Java虚拟机栈(Java Virtual Machine Stack)采用栈的数据结构来管理方法调用中的基本数据,先进后出(First In Last Out),每一个方法的调用使用一个栈帧(Stack Frame)来保存。 接下来以…...
linux系统上tomcat简介以及安装tomcat
tomcat简介以及安装 Tomcat简介安装环境安装jdk安装tomcat浏览器访问 Tomcat简介 Tomcat是一个开源的Web服务器和servlet容器,由Apache软件基金会开发和维护。它是一种流行的Java Web应用服务器,用于运行Java编写的Web应用程序。 Tomcat提供了一个轻量级…...

树莓派的pip安装时候添加清华源
每次都要去找镜像网址,太麻烦了,通过改配置可以一次性解决。 首先创建一个.pip 目录 mkdir ~/.pip意味着在当前目录下创建.pip文件,不过这个是隐藏文件,一般情况下是关闭隐藏文件的可视的,于是我绕了点弯弯。 编辑…...

共享网盘系统PHP源码
新V5.0版本,支持上传视频、支持视频播放、支持共享,也可以自己用。 可以自动生成视频外链,下载地址,播放器代码,html代码,ubb代码等等。 使用方法: 源码上传到服务器,打开网站根据…...

unity-ios-解决内购商品在Appstore上面已配置,但在手机测试时却无法显示的问题
自己这几天用 unity 2021 xcode 14.2 开发ios内购,appstore上面内购商品都已经配置好了,但是在手机里就是不显示,最后才发现必需得满足以下条件才行: 1. Appstore后台 -> 内购商品 -> 商品状态必需为『准备提交』以上状态…...
flask的基本使用 token插件(二)
一、安装flask-jwt-extended 安装flask-jwt-extend得时候 会自动安装一个pyjwt得库。pyjwt可以直接使用来生成JWT和验证。但是在flask中,可以通过Flask-JWT-Extended来实现JWT能,因为他封装了使用方式,以及一些属性和装饰器,用起…...

云计算、Docker、K8S问题
1 云计算 云计算作为一种新兴技术,已经在现代社会中得到了广泛应用。它以其高效、灵活和可扩展特性,成为了许多企业和组织在数据处理和存储方面的首选方案。 1.1 什么是云计算?它有哪些特点? 云计算是一种通过网络提供计算资源…...

【Iceberg学习二】Branch和Tag在Iceberg中的应用
Iceberg 表元数据保持一个快照日志,记录了对表所做的更改。快照在 Iceberg 中至关重要,因为它们是读者隔离和时间旅行查询的基础。为了控制元数据大小和存储成本,Iceberg 提供了快照生命周期管理程序,如 expire_snapshots…...
在 Blazor WASM 中手撸一个.NET MD5类
最近.net8 blazor auto大火, 我也玩了一下,发现ssr能用的代码 MD5 类在wasm是没法用的. 于是搜索了一下互联网,找到了一份代码,分享给大家. 我找到的帖子作者原话: 代码不是我的,但我确实稍微修改了它以使其与 System.Security.Cryptography.MD5 类更加一致。 pub…...

MFC实现遍历系统进程
今天我们来枚举系统中的进程和结束系统中进程。 认识几个API 1)CreateToolhelp32Snapshot 用于创建系统快照 HANDLE WINAPI CreateToolhelp32Snapshot( __in DWORD dwFlags, //指定快照中包含的系统内容__in DWORD th32P…...

【C语言】深入理解指针
目录 1.字符指针 2.指针数组 3.数组指针 4.数组传参与指针传参 一维数组传参 二维数组传参 一级指针传参 二级指针传参 5.函数指针 6.函数指针数组 7.指向函数指针数组的指针(了解即可) 8.回调函数 回调函数的应用:库函数qsort …...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...

Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...