基于缓存注解的时间戳令牌防重复提交设计

文章目录

  • 一,概述
  • 二,实现过程
    • 1、引入pom依赖
    • 2、定义缓存管理
    • 3、时间戳服务类
    • 4、模拟测试接口
  • 三,测试过程
    • 1, 模拟批量获取
    • 2, 消费令牌
  • 四,源码放送
  • 五,优化方向

一,概述

API接口由于需要供第三方服务调用,所以必须暴露到外网,并提供了具体请求地址和请求参数。为了防止重放攻击必须要保证请求仅一次有效

比较成熟的做法有批量颁发时间戳令牌,每次请求消费一个令牌

二,实现过程

下面我们基于本地缓存caffeine来说明具体实现。

1、引入pom依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId></dependency><!-- caffeine依赖 --><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId></dependency>

2、定义缓存管理


import java.util.concurrent.TimeUnit;import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import com.github.benmanes.caffeine.cache.Caffeine;/*** * CacheConfig* * @author 00fly* @version [版本号, 2019年12月18日]* @see [相关类/方法]* @since [产品/模块版本]*/
@Configuration
public class CacheConfig extends CachingConfigurerSupport
{@Bean@Overridepublic CacheManager cacheManager(){CaffeineCacheManager cacheManager = new CaffeineCacheManager();// 方案一(常用):定制化缓存CachecacheManager.setCaffeine(Caffeine.newBuilder().expireAfterWrite(10, TimeUnit.MINUTES).initialCapacity(100).maximumSize(10000));// 如果缓存种没有对应的value,通过createExpensiveGraph方法同步加载 buildAsync是异步加载// .build(key -> createExpensiveGraph(key))// 方案二:传入一个CaffeineSpec定制缓存,它的好处是可以把配置方便写在配置文件里// cacheManager.setCaffeineSpec(CaffeineSpec.parse("initialCapacity=50,maximumSize=500,expireAfterWrite=5s"));return cacheManager;}
}

3、时间戳服务类

注意:一定要理解为什么使用SpringContextUtils


import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.LongStream;import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;import com.fly.core.utils.SpringContextUtils;/*** TimestampService*/
@Service
public class TimestampService
{/*** 批量获取用户timestamp,支持缓存*/@Cacheable(value = "timestamp", key = "#user", unless = "#result.size()==0")public List<Long> batchGet(String user){String userId = DigestUtils.md5DigestAsHex(user.getBytes(StandardCharsets.UTF_8));if (StringUtils.isBlank(userId)){throw new RuntimeException("用户不存在");}return LongStream.range(0, 10).map(i -> System.currentTimeMillis() + i).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);}/*** 判断用户timestamp是否有效*/public boolean isFirstUse(String user, Long timestamp){// 注意:缓存基于代理实现,直接调用,缓存机制会失效TimestampService timestampService = SpringContextUtils.getBean(TimestampService.class);List<Long> data = timestampService.batchGet(user);boolean isFirstUse = data.contains(timestamp);if (isFirstUse){timestampService.removeThenUpdate(user, timestamp);}return isFirstUse;}/*** 移除用户已使用的timestamp,刷新缓存* */@CachePut(value = "timestamp", key = "#user")public List<Long> removeThenUpdate(String user, Long timestamp){// 注意:缓存基于代理实现,直接调用,缓存机制会失效TimestampService timestampService = SpringContextUtils.getBean(TimestampService.class);List<Long> data = timestampService.batchGet(user);data.remove(timestamp);if (data.size() < 5) // 及时补充{data.addAll(batchGet(user));}return data;}
}

4、模拟测试接口


import java.util.Collections;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import com.fly.core.entity.JsonResult;
import com.fly.openapi.service.TimestampService;import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;@Slf4j
@Api(tags = "接口辅助")
@RestController
@RequestMapping("/auto/help")
public class AutoHelpController
{@AutowiredTimestampService timestampService;@ApiOperation("批量获取用户timestamp")@GetMapping("/getBatchTimestamps")public JsonResult<?> getBatchTimestamps(@RequestParam String user){log.info("getBatchTimestamps for {}", user);return JsonResult.success(Collections.singletonMap("timestamps", timestampService.batchGet(user)));}@ApiOperation("消费timestamp")@GetMapping("/useTimestamp")public JsonResult<?> useTimestamp(@RequestParam String user, Long timestamp){log.info("useTimestamp for {}", user);return JsonResult.success(Collections.singletonMap("isFirstUse", timestampService.isFirstUse(user, timestamp)));}
}

三,测试过程

1, 模拟批量获取

输入用户名00fly
在这里插入图片描述

2, 消费令牌

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四,源码放送

https://gitcode.com/00fly/springboot-openapi

git clone https://gitcode.com/00fly/springboot-openapi.git

五,优化方向

  1. 批量获取令牌可采用https、tcp、grpc等更加安全的协议获的
  2. 获取令牌可以考虑采用非对称加密算法鉴权
  3. 多实例部署,可切换到分布式缓存,如redis

有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!

-over-

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PHP源码_最新Ai对话系统网站源码 ChatGPT+搭建教程+前后端

基于ChatGPT开发的一个人工智能技术驱动的自然语言处理工具&#xff0c;它能够通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人类一样来聊天交流&#xff0c;甚至能完成撰写邮件、视频脚本、文案、翻译、代码&#xff0c;写论…

C++Day6作业

1、模板实现顺序栈 #include <iostream>using namespace std;template <typename T> class Stack {T* S; //数组int size;//栈容量int top; //栈顶元素下标 public://有参构造Stack(int size):S(new T[size]),size(size),top(-1){}//初始化时直接将栈顶元素下标设…

记一次古董级netapp存储更换故障硬盘全过程

1、案例背景 记一次某医院PACS存储NetApp FAS2554更换故障硬盘的过程。 这个netapp设备以前从未调试过&#xff0c;据客户说该设备上线也有快9年了&#xff0c;头一次故障硬盘。因为己经过保了&#xff0c;客户只是采购的硬盘&#xff0c;我这来免费服务了。。。 netapp调试…

LeetCode 110.平衡二叉树(Java/C/Python3/Go实现含注释说明,Easy)

标签 树深度优先搜索递归 题目描述 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡的二叉树定义为&#xff1a; 一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1。 原题&#xff1a;LeetCode 110.平衡二叉树 思路及…

『跨端框架』Flutter环境搭建

『跨端框架』Flutter环境搭建 资源网站简介跨平台高性能发展历程跨平台框架的比较成功案例 环境搭建&#xff08;windows&#xff09;基础环境搭建Windows下的安卓环境搭建Mac下的安卓环境配置资源镜像JDKAndroid StudioFlutter SDK问题一问题二问题三修改项目中的Flutter版本 …

Android14之解决报错:libncurses.so.5与libtinfo.so.5缺少问题(二百零九)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【数据库主从架构】

【数据库主从架构】 1. 什么是数据库的主从架构1.1 主从复制1.1.1 MySQL的主从主从复制技术三级目录 1. 什么是数据库的主从架构 随着公司业务线的增多&#xff0c;各种数据都在迅速增加&#xff0c;并且数据的读取流量也大大增加&#xff0c;就面临着数据安全问题&#xff0c;…

Spring Boot | Spring Security ( SpringBoot安全管理 )、Spring Security中 的 “自定义用户认证“

目录 : Spring Boot 安全管理 &#xff1a;一、Spring Security 介绍二、Spring Security 快速入门2.1 基础环境搭建 :① 创建Spring Boot 项目② 创建 html资源文件③ 编写Web控制层 2.2 开启安全管理效果测试 :④ 添加 spring-boot-starter-security 启动器⑤ 项目启动测试 三…

Vue Cli脚手架—安装Nodejs和Vue Cli

一&#xff0c;Vue Cli 文档地址: https://cli.vuejs.org/zh/ 二&#xff0c;.环境配置&#xff0c;搭建项目 1.安装node.js 2.下载 node.js10.16.3 地址: https://nodejs.org/en/blog/release/v10.16.3/ 3.安装 node.js10.16.3 , 直接下一步即可, 安装到 d:\program\nodejs…

【kettle006】kettle访问华为openGauss高斯数据库并处理数据至execl文件

1.一直以来想写下基于kettle的系列文章&#xff0c;作为较火的数据ETL工具&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 2.熟悉、梳理、总结下华为openGauss高斯数据库相关知识体系 3.欢迎批评指正&#xff0c;跪谢…

浅论汽车研发项目数字化管理之道

随着汽车行业竞争不断加剧&#xff0c;汽车厂商能否快速、高质地推出贴合市场需求的新车型已经成为车企竞争的重要手段&#xff0c;而汽车研发具备流程复杂、专业领域多、协作难度大、质量要求高等特点&#xff0c;企业如果缺少科学健全的项目管理体系&#xff0c;将会在汽车研…

低空经济+飞行汽车:eVTOL技术详解

低空经济是以各种有人驾驶和无人驾驶航空器的各类低空飞行活动为牵引&#xff0c;辐射带动相关领域融合发展的综合性经济形态。它广泛体现于第一、第二、第三产业之中&#xff0c;在促进经济发展、加强社会保障、服务国防事业等方面发挥着日益重要的作用。 飞行汽车&#xff0c…

SpringBoot配置HTTPS及开发调试

前言 在实际开发过程中&#xff0c;如果后端需要启用https访问&#xff0c;通常项目启动后配置nginx代理再配置https&#xff0c;前端调用时高版本的chrome还会因为证书未信任导致调用失败&#xff0c;通过摸索整理一套开发调试下的https方案&#xff0c;特此分享 后端配置 …

“酒店涨价?火车票难求?看‘房贷自由族’如何玩转最燃五一“

今年五一&#xff0c;很可能是近几年旅游最疯狂的一年——虽然酒店价格狂飙好几倍&#xff0c;也抢不到火车票&#xff0c;人们却依然有着疯狂的出游和消费欲望。 ​最直接的原因大概是很多人离开了房贷&#xff0c;活明白了吧。就拿我身边的一些房奴们来说&#xff0c;已经陆…

大数据面试题 —— Spark数据倾斜及其解决方案

目录 1 调优概述2 数据倾斜发生时的现象3 数据倾斜发生的原理4 如何定位导致数据倾斜的代码4.1 某个 task 执行特别慢的情况4.2 某个 task 莫名其妙内存溢出的情况5 查看导致数据倾斜的 key 的数据分布情况6 数据倾斜的解决方案6.1 使用 Hive ETL 预处理数据6.2 过滤少数导致倾…

【Java EE】Mybatis之XML详解

文章目录 &#x1f38d;配置数据库连接和MyBatis&#x1f340;写持久层代码&#x1f338;添加mapper接口&#x1f338;添加UserInfoXMLMapper.xml&#x1f338;单元测试 &#x1f332;CRUD&#x1f338;增(Insert)&#x1f338;删(Delete)&#x1f338;改(Update)&#x1f338;…

GaussDB数据库事务管理

一、引言 事务管理是数据库系统中至关重要的一部分&#xff0c;它确保了数据库的一致性和可靠性。在GaussDB数据库中&#xff0c;事务管理不仅遵循传统的ACID特性&#xff0c;还提供了一些高级功能。本文将深入探讨GaussDB数据库事务管理的各个方面。 二、事务的基本概念 2.1…

es环境安装及php对接使用

Elasticsearch Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口。Elasticsearch是用Java语言开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是一种流行的…

【小沐学Java】VSCode搭建Java开发环境

文章目录 1、简介2、安装VSCode2.1 简介2.2 安装 3、安装Java SDK3.1 简介3.2 安装3.3 配置 4、安装插件Java Extension Pack4.1 简介4.2 安装4.3 配置 结语 1、简介 2、安装VSCode 2.1 简介 Visual Studio Code 是一个轻量级但功能强大的源代码编辑器&#xff0c;可在桌面上…

FP16、BF16、INT8、INT4精度模型加载所需显存以及硬件适配的分析

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…