redis 缓存jwt令牌设置更新时间 BUG修复

2024-06-16 23:36

本文主要是介绍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修复的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067871

相关文章

Redis 的 SUBSCRIBE命令详解

《Redis的SUBSCRIBE命令详解》Redis的SUBSCRIBE命令用于订阅一个或多个频道,以便接收发送到这些频道的消息,本文给大家介绍Redis的SUBSCRIBE命令,感兴趣的朋友跟随... 目录基本语法工作原理示例消息格式相关命令python 示例Redis 的 SUBSCRIBE 命令用于订

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

sky-take-out项目中Redis的使用示例详解

《sky-take-out项目中Redis的使用示例详解》SpringCache是Spring的缓存抽象层,通过注解简化缓存管理,支持Redis等提供者,适用于方法结果缓存、更新和删除操作,但无法实现... 目录Spring Cache主要特性核心注解1.@Cacheable2.@CachePut3.@Ca

JWT + 拦截器实现无状态登录系统

《JWT+拦截器实现无状态登录系统》JWT(JSONWebToken)提供了一种无状态的解决方案:用户登录后,服务器返回一个Token,后续请求携带该Token即可完成身份验证,无需服务器存储会话... 目录✅ 引言 一、JWT 是什么? 二、技术选型 三、项目结构 四、核心代码实现4.1 添加依赖(pom

修复已被利用的高危漏洞! macOS Sequoia 15.6.1发布

《修复已被利用的高危漏洞!macOSSequoia15.6.1发布》苹果公司于今日发布了macOSSequoia15.6.1更新,这是去年9月推出的macOSSequoia操作... MACOS Sequoia 15.6.1 正式发布!此次更新修复了一个已被黑客利用的严重安全漏洞,并解决了部分中文用户反馈的

Redis实现高效内存管理的示例代码

《Redis实现高效内存管理的示例代码》Redis内存管理是其核心功能之一,为了高效地利用内存,Redis采用了多种技术和策略,如优化的数据结构、内存分配策略、内存回收、数据压缩等,下面就来详细的介绍... 目录1. 内存分配策略jemalloc 的使用2. 数据压缩和编码ziplist示例代码3. 优化的

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

C# LiteDB处理时间序列数据的高性能解决方案

《C#LiteDB处理时间序列数据的高性能解决方案》LiteDB作为.NET生态下的轻量级嵌入式NoSQL数据库,一直是时间序列处理的优选方案,本文将为大家大家简单介绍一下LiteDB处理时间序列数... 目录为什么选择LiteDB处理时间序列数据第一章:LiteDB时间序列数据模型设计1.1 核心设计原则

使用Spring Cache本地缓存示例代码

《使用SpringCache本地缓存示例代码》缓存是提高应用程序性能的重要手段,通过将频繁访问的数据存储在内存中,可以减少数据库访问次数,从而加速数据读取,:本文主要介绍使用SpringCac... 目录一、Spring Cache简介核心特点:二、基础配置1. 添加依赖2. 启用缓存3. 缓存配置方案方案

基于Redis自动过期的流处理暂停机制

《基于Redis自动过期的流处理暂停机制》基于Redis自动过期的流处理暂停机制是一种高效、可靠且易于实现的解决方案,防止延时过大的数据影响实时处理自动恢复处理,以避免积压的数据影响实时性,下面就来详... 目录核心思路代码实现1. 初始化Redis连接和键前缀2. 接收数据时检查暂停状态3. 检测到延时过