令牌主动失效机制范例(利用redis)注释分析

news/2024/10/10 20:56:52/

介绍该机制

  1. 令牌生成
    在需要限流的场景中,系统会根据一定的速率生成令牌,存储在 Redis 中。可以设定每秒生成的令牌数量。

  2. 令牌获取
    当用户请求时,系统会从 Redis 中获取令牌。可以使用原子性操作(如 DECR)来确保令牌的正确获取和减少。

  3. 令牌失效
    令牌的主动失效可以通过设定过期时间(TTL)来实现。当生成的令牌在一定时间内未被消费,Redis 会自动删除这些令牌。也可以通过在逻辑上判断令牌的使用情况,主动将过期的令牌从队列中剔除。

  4. 监控与调整
    在实际运行中,可以通过 Redis 的发布/订阅机制或键空间通知(Keyspace Notifications)来监控令牌的状态,动态调整生成速率或失效策略。

redis_13">redis令牌失效机制的代码实现案例

redis_14">redis配置

pom、yml(redis配置)
在这里插入图片描述

redis的配置文件

package com.itheima.config;import org.springframework.cache.annotation.CachingConfigurerSupport; // 引入缓存支持类
import org.springframework.context.annotation.Bean; // 引入Bean注解
import org.springframework.context.annotation.Configuration; // 引入配置注解
import org.springframework.data.redis.connection.RedisConnectionFactory; // 引入Redis连接工厂
import org.springframework.data.redis.core.RedisTemplate; // 引入通用Redis模板
import org.springframework.data.redis.core.StringRedisTemplate; // 引入字符串Redis模板@Configuration // 声明这是一个配置类
public class RedisConfig extends CachingConfigurerSupport { // 继承缓存支持类// 定义一个StringRedisTemplate Bean,用于操作String类型的键值对@Beanpublic StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {// 使用提供的连接工厂创建StringRedisTemplate实例return new StringRedisTemplate(redisConnectionFactory);}// 定义一个通用的RedisTemplate Bean,用于操作任意类型的对象@Beanpublic RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {// 创建RedisTemplate实例RedisTemplate<String, Object> template = new RedisTemplate<>();// 设置连接工厂,以便连接到Redis服务器template.setConnectionFactory(redisConnectionFactory);// 返回配置好的RedisTemplate实例return template;}
}

用户控制器(登录)

usercontroller

    @PostMapping("/login")public Result<String> login(@Pattern(regexp = "^\\S{5,16}$") String username, @Pattern(regexp = "^\\S{5,16}$") String password) {//根据用户名查询用户User loginUser = userService.findByUserName(username);//判断该用户是否存在if (loginUser == null) {return Result.error("用户名错误");}//判断密码是否正确  loginUser对象中的password是密文if (Md5Util.getMD5String(password).equals(loginUser.getPassword())) {//登录成功Map<String, Object> claims = new HashMap<>();  // 创建一个存储用户信息的映射claims.put("id", loginUser.getId());           // 将用户 ID 存储在 claims 中claims.put("username", loginUser.getUsername()); // 将用户名存储在 claims 中String token = JwtUtil.genToken(claims);       // 生成 JWT,包含用户的 ID 和用户名//把token存储到redis中ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set(token,token,1, TimeUnit.HOURS);return Result.success(token);}return Result.error("密码错误");}

使用完需要删除操作(usercontroller)

        //删除redis中对应的tokenValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.getOperations().delete(token);return Result.success();

拦截器里redis的验证

logininterceptor
@Component
public class LoginInterceptor implements HandlerInterceptor {@Autowiredprivate StringRedisTemplate stringRedisTemplate; // 注入 Redis 模板,用于操作 Redis 数据库@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 令牌验证String token = request.getHeader("Authorization"); // 从请求头中获取名为 "Authorization" 的令牌// 验证 tokentry {// 从 Redis 中获取与请求中相同的 tokenValueOperations<String, String> operations = stringRedisTemplate.opsForValue();String redisToken = operations.get(token); // 查询 Redis 数据库if (redisToken == null) {// 如果 Redis 中没有该 token,说明 token 已经失效throw new RuntimeException("Token has expired"); // 抛出异常以指示 token 失效}// 解析 token,获取业务数据(例如用户信息)Map<String, Object> claims = JwtUtil.parseToken(token);// 将业务数据存储到 ThreadLocal 中,以便后续处理使用ThreadLocalUtil.set(claims);// 放行请求,继续处理return true;} catch (Exception e) {// 如果发生异常(例如 token 失效),设置 HTTP 响应状态码为 401(未授权)response.setStatus(401);// 拦截请求,不放行return false;}}
}

测试
redisTest

package com.itheima;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;import java.util.concurrent.TimeUnit;@SpringBootTest     //如果在测试类上添加了这个注解,那么将来单元测试方法执行之前,会先初始化Spring容器
public class RedisTest {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void testSet(){//往redis中存储一个键值对  StringRedisTemplateValueOperations<String, String> operations = stringRedisTemplate.opsForValue();operations.set("username","zhangsan");operations.set("id","1",15, TimeUnit.SECONDS);}@Testpublic void testGet(){//从redis中获取一个键值对ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();System.out.println(operations.get("id"));}
}

http://www.ppmy.cn/news/1537116.html

相关文章

view deign 和 vue2 合并单元格的方法

1.vue版本和view design 版本 {"vue": "^2.6.11","view-design": "^4.7.0", }2.Data中定义数据 spanArr: [], // 某一列下需要合并的行数 pos: 0// 索引// 注意点&#xff1a; 在获取列表前&#xff0c;需要重置 this.spanArr [] 注…

## jupyter_server

$ conda install -c conda-forge jupyter_server 查看配置文件路径 $ jupyter --pathsconfig:/home/musk/.jupyter/home/musk/anaconda3/etc/jupyter/usr/local/etc/jupyter/etc/jupyter data:/home/musk/.local/share/jupyter/home/musk/anaconda3/share/jupyter/usr/local/s…

一文解读数据中台附搭建指南

数据是企业的核心资产&#xff0c;更是企业数字化转型的关键驱动力。为了更好地管理和利用数据&#xff0c;进行数据共享&#xff0c;充分发挥数据的作用&#xff0c;越来越多的企业开始构建实时数据中台。 一数据中台 定义&#xff1a;数据中台是将企业内部各个部门、系统、应…

高程系统详解及85高程在现代测量中的应用

软考鸭微信小程序 学软考,来软考鸭! 提供软考免费软考讲解视频、题库、软考试题、软考模考、软考查分、软考咨询等服务 高程系统&#xff0c;作为地理信息系统&#xff08;GIS&#xff09;、遥感技术及工程测量中的核心概念&#xff0c;是描述地球表面任意点相对于某一基准面的…

新手教学系列——爬虫异步并发注意事项

引言 爬虫是网络数据采集中不可或缺的工具,很多程序员在入门时会遇到这样的问题:为什么我的爬虫这么慢?尤其在面对大量数据时,单线程爬虫的速度可能让人捶胸顿足。随着爬虫规模的增大,异步并发成为了提高爬取效率的关键。然而,异步并发并不像表面看起来那么简单,如果没…

关系数据库和关系模型(1)

昨天补充了DBMS概况的存储管理层面&#xff0c;今天来详细介绍数据库管理系统中常见且应用广泛的关系型数据库&#xff08;简称关系数据库&#xff09;&#xff0c;比如postgreSQL、MySQL、Oracle Database。 关系模型 关系模型是数据库中如何进行存储和组织数据的理论基础。…

MQ 架构设计原理与消息中间件详解(三)

RabbitMQ实战解决方案 RabbitMQ死信队列 死信队列产生的背景 RabbitMQ死信队列俗称&#xff0c;备胎队列&#xff1b;消息中间件因为某种原因拒收该消息后&#xff0c;可以转移到死信队列中存放&#xff0c;死信队列也可以有交换机和路由key等。 产生死信队列的原因 消息投…

ubuntu 18.04虚拟机以太网网段与地平线J6板端连接配置

目录 1、板端IP地址确认 2、本机以太网端ip设置 3、虚拟机设置nat模式 4、虚拟机虚拟网络编辑 5、虚拟机端ip设置 6、虚拟机端验证是否可以ping通板端ip及是否可以联网 1、板端IP地址确认 ip&#xff1a;192.168.98.233 2、本机以太网端ip设置 ip&#xff1a; 3、虚拟…