redis 缓存jwt令牌设置更新时间 BUG修复
大家好,今天我又又又来了,hhhhh。
上文中 我们永redis缓存了token 但是我们发现了 一个bug ,redis中缓存的token 是单用户才能实现的。
就是 我 redis中存储的键 名 为token 值 是jwt令牌 ,但是如果 用户a 登录 之后 创建一个 键 为token的 键值对,如果用户b登录,创建的的键名也是 token ,这样用户b的 jwt 会覆盖 用户a的,就会导致 用户a 的token 会失效呀,这真是一个大大的bug , 按照我目前的水平,我想到了一下 的解决方案 ,既然 token 的键会覆盖,那么我们给 token的键 加上一个唯一标识不就好了
解决前的代码
package com.example.getway.globalfilter;import cn.hutool.core.collection.CollUtil;
import com.example.getway.Untils.JwtUntils;
import com.example.getway.commen.MessageConstant;
import com.example.getway.pojo.JwtProperties;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
@RequiredArgsConstructor
@Slf4j
@Component
public class TokenGlobalFilter implements GlobalFilter, Ordered {private final JwtProperties jwtProperties;private final RedisTemplate redisTemplate;// 这个过滤器 请求的转发@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//我们只要是非登录请求全都要检验jwt 然后进行 用户信息的传递//获取request对象ServerHttpRequest request = exchange.getRequest();RequestPath requestPath = request.getPath();if(requestPath.toString().contains("/userLogin")){return chain.filter(exchange);}//获取请求头的 token
// String redisToken =null;
// List<String> authorization = request.getHeaders().get("authorization");
// if (!CollUtil.isEmpty(authorization)) {
// redisToken = authorization.get(0);
// }String redisToken = (String)redisTemplate.opsForValue().get(MessageConstant.TOKEN);log.info("token:{}",redisToken);if (redisToken != null ) {//进行jwt的解析try {Claims claims = JwtUntils.parseJwt(redisToken, jwtProperties.getSecretkey());//每次 访问其他资源的时候 都把token更新redisTemplate.expire(MessageConstant.TOKEN, 1000, TimeUnit.DAYS);String loginId = claims.get(MessageConstant.LOGIN_ID).toString();log.info("网关层当前用户的id:{}", Long.valueOf(loginId));//证明 token有效 传递用户信息ServerWebExchange loginId1 = exchange.mutate().request(b -> b.header("loginId", loginId)).build();return chain.filter(loginId1);} catch (Exception e) {log.info("{}",e.getMessage());//出现异常返回一个异常响应ServerHttpResponse response = exchange.getResponse();response.setRawStatusCode(401);return response.setComplete();}}log.info("token错误");return exchange.getResponse().setComplete();}
//过滤器链中的优先级 数值越低 优先级就越高@Overridepublic int getOrder() {return 0;}
}
解决前的登陆代码
package com.example.logindemo.cotroller;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.logindemo.Untils.JwtUntils;
import com.example.logindemo.commen.MessageConstant;
import com.example.logindemo.pojo.JwtProperties;
import com.example.logindemo.pojo.po.UserLogin;
import com.example.logindemo.result.Result;
import com.example.logindemo.service.UserLoginService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;@RestController
@Slf4j
@RequiredArgsConstructor
public class LoginController {private final UserLoginService userLoginService;private final JwtProperties jwtProperties;private final RedisTemplate redisTemplate;@PostMapping("/userLogin")public Result userLogin( String username, String password) {password=DigestUtils.md5DigestAsHex(password.getBytes());LambdaQueryWrapper<UserLogin> userLoginLambdaQueryWrapper = new LambdaQueryWrapper<UserLogin>().eq(UserLogin::getUsername, username);UserLogin userLogin = userLoginService.getOne(userLoginLambdaQueryWrapper);if(userLogin==null && userLogin.getUsername().isEmpty()){return Result.error("查询不到用户");}if (username.equals(userLogin.getUsername()) && password.equals(userLogin.getPassword())) {//需要一个map集合 传什么 解析出来什么 一般传的是登录用户的id 我们传1HashMap<String, Object> map = new HashMap<>();map.put(MessageConstant.LOGIN_ID, userLogin.getId());String token = JwtUntils.CreateJwt(map, jwtProperties.getSecretkey());//设置redis缓存为1000天redisTemplate.opsForValue().set(MessageConstant.TOKEN,token,1000,TimeUnit.DAYS);return Result.success(token);}return Result.error("未知错误");}}
解决后 的登录代码 这里只放修改部分

解决后的 网关层过滤代码

现在 我们手动在数据库添加 一个用户

我们apifox进行登录接口的依次登录 ,然后观察 redis中的缓存数据

发现token 2 存在 我们也就设置成功了
相关文章:
redis 缓存jwt令牌设置更新时间 BUG修复
大家好,今天我又又又来了,hhhhh。 上文中 我们永redis缓存了token 但是我们发现了 一个bug ,redis中缓存的token 是单用户才能实现的。 就是 我 redis中存储的键 名 为token 值 是jwt令牌 ,但是如果 用户a 登录 之后 创建一个…...
nginx精准禁止特定国家或者地区IP访问
1、安装依赖 dnf -y install gcc-c libtool gd-devel pcre pcre-devel openssl openssl-devel zlib zlib-devel libmaxminddb-devel pcre-devel zlib-devel gcc gcc-c make git2、获取NGINX安装包并安装 wget https://nginx.org/download/nginx-1.26.1.tar.gz git clone http…...
单片机课设-基于单片机的电子时钟设计(仿真+代码+报告)
基于单片机的电子时钟设计 前言一、课设任务是什么?二、系统总体方案硬件设计2.1 系统硬件总体设计2.2 键盘电路设计2.3 DS1302实时时钟芯片电路设计2.4 复位电路2.5 LCD电路设计 三、软件设计3.1 主程序流程图3.2 主要程序设计代码3.3 修改时间函数3.4 扫描键盘函数 四、仿真…...
.net 6 api 修改URL为小写
我们创建的api项目,url是[Route(“[controller]”)],类似这样子定义的。我们的controller命名是大写字母开头的,显示在url很明显不是很好看(url不区分大小写)。转换方式: var builder WebApplication.Crea…...
Windows电脑部署Jellyfin服务端并进行远程访问配置详细教程
文章目录 前言1. Jellyfin服务网站搭建1.1 Jellyfin下载和安装1.2 Jellyfin网页测试 2.本地网页发布2.1 cpolar的安装和注册2.2 Cpolar云端设置2.3 Cpolar本地设置 3.公网访问测试4. 结语 前言 本文主要分享如何使用Windows电脑本地部署Jellyfin影音服务并结合cpolar内网穿透工…...
rsync同步目录脚本
假设有两台服务器的示例 IP 地址为: Server A: 192.168.1.100Server B: 192.168.1.200 现在来解释如何使用这个脚本进行服务器之间文件夹内容的同步,保留路径和服务器信息的抽象化。 1. 脚本文件位置和权限 假设脚本文件位于 /root/script.sh&#x…...
LeetCode 6. Z 字形变换
LeetCode 6. Z 字形变换 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下: 之后,你的输出需要从左往右逐行读取,产生…...
RTC实时时钟
一、Unix时间戳 1、Unix 时间戳 (1)Unix 时间戳(Unix Timestamp)定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数,不考虑闰秒 (2)时间戳存储在一个秒计数器中,秒计数器为…...
WHAT - React 学习系列(一)
官方文档 If you have a lot of HTML to port to JSX, you can use an online converter. You’ll get two things from useState: the current state (count), and the function that lets you update it (setCount). To “remember” things, components use state.To mak…...
代理模式(静态代理/动态代理)
代理模式(Proxy Pattern) 一 定义 为其他对象提供一种代理,以控制对这个对象的访问。 代理对象在客户端和目标对象之间起到了中介作用,起到保护或增强目标对象的作用。 属于结构型设计模式。 代理模式分为静态代理和动态代理。…...
Word2Vec基本实践
系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目…...
IIS配置網站登錄驗證,禁止匿名登陸
需要維護一個以前的舊系統,這個系統在內網運行,需要抓取電腦的登陸賬號,作為權限管理的一部分因此需要在IIS配置一下...
抖音矩阵系统搭建,AI剪辑短视频,一键管理矩阵账号
目录 前言: 一、抖音矩阵系统有哪些功能? 1.AI智能文案 2.多平台账号授权 3.多种剪辑模式 4. 矩阵一键发布,智能发布 5.抖音爆店码功能 6.私信实时互动 7.去水印及外链 二、抖音矩阵系统可以解决哪些问题? 总结ÿ…...
山东大学软件学院创新项目实训开发日志——收尾篇
山东大学软件学院创新项目实训开发日志——收尾篇 项目名称:ModuFusion Visionary:实现跨模态文本与视觉的相关推荐 -------项目目标: 本项目旨在开发一款跨模态交互式应用,用户可以上传图片或视频,并使用文本、点、…...
vue2.7支持组合式API,但是对应的vue-router3并不支持useRoute、useRouter。
最近在做一个项目,因为目标用户浏览器版本并不确定,可能会有较旧版本,于是采用vue2.7而不是vue3,最近一年多使用vue3开发的项目都碰到了很多chrome 63-73版本,而对应UI 库 element plus又问题很多。 为了不碰到这些问…...
摊位纠纷演变肢体冲突,倒赔了500:残疾夫妇与摊主谁之过?
在一个小商贩密集的街区,一起由摊位纠纷引发的肢体冲突事件在当地社区和网络上引起了热议。涉事双方为一名摊主和一对残疾夫妇,他们的争执源自对一个摊位的使用权。本是口头上的争吵,却由于双方情绪激动,迅速升级为肢体冲突&#…...
深入理解和实现Windows进程间通信(消息队列)
常见的进程间通信方法 常见的进程间通信方法有: 管道(Pipe)消息队列共享内存信号量套接字 下面,我们将详细介绍消息队列的原理以及具体实现。 什么是消息队列? Windows操作系统使用消息机制来促进应用程序与操作系…...
Web网页前端教程免费:引领您踏入编程的奇幻世界
Web网页前端教程免费:引领您踏入编程的奇幻世界 在当今数字化时代,Web前端技术已成为互联网发展的重要驱动力。想要踏入这一领域,掌握相关技能,却苦于找不到合适的教程?别担心,本文将为您带来一份免费的We…...
北斗短报文终端在应急消防通信场景中的应用
在应对自然灾害和紧急情况时,北斗三号短报文终端以其全球覆盖、实时通信和精准定位的能力,成为应急消防通信的得力助手。它不仅能够在地面通信中断的极端条件下保障信息传递的畅通,还能提供精准的位置信息,为救援行动提供有力支持…...
Java跳动爱心代码
1.计算爱心曲线上的点的公式 计算爱心曲线上的点的公式通常基于参数方程。以下是两种常见的参数方程表示方法,用于绘制爱心曲线: 1.1基于 (x, y) 坐标的参数方程 x a * (2 * cos(θ) - sin(θ))^3 y a * (2 * sin(θ) - cos(θ))^3 其中ÿ…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
