防止请求重复提交:注解+拦截器的实现方案

news2024/12/26 13:58:19

文章目录

    • 了解请求重复提交
    • 解决思路
    • 具体实现

了解请求重复提交

请求重复提交是指用户在一次请求还未处理完成时,重复提交了相同的请求。这种情况通常发生在网络延迟、用户误操作或系统性能不佳等情况下。

请求重复提交可能会导致以下问题和影响:

  1. 数据不一致:如果重复提交的请求包含了对数据的修改操作,那么可能会导致数据不一致的问题,例如重复购买商品、重复支付订单等。

  2. 系统资源浪费:重复提交的请求会占用系统资源,导致服务器负载过高、响应时间变慢等问题,影响系统性能和用户体验。

  3. 安全问题:某些敏感操作(如支付、修改密码等)如果被重复提交,可能会导致安全问题,例如重复支付导致资金损失、重复修改密码导致账号被盗等。

因此,防止请求重复提交是保证系统数据一致性、提高系统性能和保障系统安全的重要措施。

解决思路

在 Spring Boot 中有效地防止用户在短时间内重复提交表单或请求,我们可以结合 Redis 来实现这个功能,我们可以将用户的请求信息存储在缓存中,这样我们就可以实时跟踪用户请求的状态,同时也可以提高系统的性能。为了限制用户在短时间内重复提交相同的请求,我们可以设置一个时间间隔来限制重复提交。用户在指定时间间隔内提交相同的请求时,将返回一个错误信息,否则请求将被正常处理。因此,通过这个方法,我们可以有效地防止用户在短时间内提交重复的请求,避免系统资源的浪费。通常情况下,我们可以使用注解+拦截器的方式来实现这个功能。

注解是一种在代码中添加元数据的方式,它可以为方法、类、字段等添加额外的信息。在请求重复提交的场景中,我们可以通过在方法或接口上添加自定义注解,在运行时通过反射机制来获取并解析注解信息,从而执行相应的逻辑。

而拦截器则是一种在请求到达控制器之前对请求进行处理的组件。它可以拦截请求,并在请求到达目标处理程序之前或之后执行一些预处理或后处理操作。

具体工作流程图如下:

image-20231028152416711

具体实现

  1. 首先我们需要创建一个自定义注解,用于标记需要进行重复请求拦截的方法。例如,我们在项目中创建一个名为@RepeatSubmit的注解:

    @Inherited
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface RepeatSubmit {
    
        /**
         * 间隔时间(ms),小于此时间视为重复提交
         */
        public int interval() default 60000;
    
        /**
         * 提示消息
         */
        public String message() default "不允许重复提交,请稍候再试";
    
    }
    
  2. 创建一个拦截器类,用于拦截带有@RepeatSubmit注解的请求。在拦截器中,可以通过保存请求的唯一标识(如token)来判断请求是否已经被处理过。

    @Component
    public class RepeatSubmitInterceptor implements HandlerInterceptor {
    
        @Autowired
        private RedisCache redisCache;
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            // 判断处理器对象是否为HandlerMethod类型
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                Method method = handlerMethod.getMethod();
    
                // 获取方法上的RepeatSubmit注解
                RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
    
                if (annotation != null) {
                    // 获取请求的IP地址、URI、请求方法、请求参数和请求体
                    String ipAddr = IpUtils.getIpAddr(request);
                    String requestURI = request.getRequestURI();
                    String requestMethod = request.getMethod();
                    Map<String, String> requestParams = ServletUtils.getRequestParams(request);
                    Map<String, String> requestBody = ServletUtils.getRequestBody(request);
    
                    // 创建缓存数据对象,并将请求信息存入其中
                    Map<String,Object> cacheData = new HashMap<>();
                    cacheData.put("ip",ipAddr);
                    cacheData.put("uri",requestURI);
                    cacheData.put("method",requestMethod);
                    cacheData.put("params",requestParams);
                    cacheData.put("body",requestBody);
    
                    // 将缓存数据进行MD5加密
                    String md5V = MD5Utils.encrypt(cacheData);
    
                    // 在Redis缓存中设置缓存对象,如果已存在则返回false
                    Boolean b = redisCache.setCacheObjectIfAbsent("repeat_submit:"+ipAddr+":"+md5V, cacheData, annotation.interval(), TimeUnit.MILLISECONDS);
    
                    if(b){
                        // 如果缓存设置成功,则放行请求
                        return true;
                    }else {
                        // 如果缓存已存在,则返回重复提交错误信息
                        AjaxResult ajaxResult = AjaxResult.error(annotation.message());
                        ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
                        return false;
                    }
                }
    
                // 如果方法没有RepeatSubmit注解,则放行请求
                return true;
            }else {
                // 如果处理器对象不是HandlerMethod类型,则放行请求
                return true;
            }
        }
    
    }
    
  3. 在Spring Boot的配置类中注册拦截器:

    @Configuration
    public class WebMvcConfig implements WebMvcConfigurer {
    
        @Autowired
        private RepeatSubmitInterceptor repeatSubmitInterceptor;
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry
                .addInterceptor(repeatSubmitInterceptor)
                .addPathPatterns("/**");
        }
        
    }
    
  4. 在需要进行重复请求拦截的方法上添加@DuplicateSubmitToken注解:

    @Controller
    public class MyController {
    
        @RequestMapping("/submit")
        @RepeatSubmit
        public String submit() {
            // 处理请求逻辑
            return "success";
        }
    }
    
  5. 启动项目,使用 ApiFox 发起请求访问/submit接口,发送成功:

    image-20231028144719930

  6. 请求发送成功后,查看Redis中的缓存数据,包含我们请求时接口数据:

    image-20231028144758402

  7. 再次发起同样的请求,直接返回提示信息“不允许重复提交,请稍候再试”:

    image-20231028144902473

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

学习笔记:二分图

二分图 引入 二分图又被称为二部图。 二分图就是可以二分答案的图。 二分图是节点由两个集合组成&#xff0c;且两个集合内部没有边的图。换言之&#xff0c;存在一种方案&#xff0c;将节点划分成满足以上性质的两个集合。 性质 如果两个集合中的点分别染成黑色和白色&am…

C语言之 结构体,枚举,联合

目录 1.结构体 1.1结构的基础知识 1.2结构的声明 1.3 特殊的声明 1.4 结构的自引用 1.5 结构体变量的定义和初始化 1.6 结构体内存对齐 1.7 修改默认对齐数 1.8 结构体传参 2. 位段 2.1 什么是位段 2.2位段的内存分配 2.3 位段的跨平台问题 3. 枚举 3.1 枚举类型…

Mybatis简介(二)

1、多表映射 简介一 链接 对于数据库的操作&#xff0c;很多时候我们都是在多表的基础上进行操作的&#xff0c;在这里讲一下多表属性值与列名映射。 案例&#xff1a;这里有一个订单表和一个客户表 CREATE TABLE t_customer (customer_id INT NOT NULL AUTO_INCREMENT, cus…

在 Elasticsearch 中丰富你的 Elasticsearch 文档

作者&#xff1a;David Pilato 对于 Elasticsearch&#xff0c;我们知道联接应该在 “索引时” 而不是查询时完成。 本博文是一系列三篇博文的开始&#xff0c;因为我们可以在 Elastic 生态系统中采取多种方法。 我们将介绍如何在 Elasticsearch 中做到这一点。 下一篇博文将介…

node实战——后端koa结合jwt连接mysql实现权限登录(node后端就业储备知识)

文章目录 ⭐前言⭐ 环境准备⭐ 实现过程⭐ mysql 配置⭐路由前的准备⭐账号注册生成token⭐账号登录生成token⭐token登录 ⭐ 自测过程截图⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于node实战——后端koa项目配置jwt实现登录注册&#xff08;n…

1230. K倍区间(前缀和)

题目&#xff1a; 1230. K倍区间 - AcWing题库 突破口&#xff1a; 区间遍历枚举一般先枚举右端点&#xff0c;再枚举左端点&#xff0c;注意由右端点限制左端点 思路&#xff1a;1.暴力 #include<cstdio> #include<iostream> #include<algorithm> #incl…

Win 7 VPN拨号错误734.

正在验证用户名和密码错误 734: PPP 链接控制协议终止。 如果您继续收到错误信息&#xff0c;您可以启用日志记录来做分析。 其他电脑拨号都成功.就这个电脑不行.找了很久,修改之后报好成功 ************************** 找到是跟下面两个两个注册表信息有关,尤其是第一个我…

基于Pytest+Requests+Allure实现接口自动化测试!

一、整体结构 框架组成&#xff1a;pytestrequestsallure设计模式&#xff1a; 关键字驱动项目结构&#xff1a; 工具层&#xff1a;api_keyword/参数层&#xff1a;params/用例层&#xff1a;case/数据驱动&#xff1a;data_driver/数据层&#xff1a;data/逻辑层&#xff1a…

75 寻找旋转排序数组中的最小值

寻找旋转排序数组中的最小值 题解1 一次循环(正确理解题意)题解2 二分 已知一个长度为 n 的数组&#xff0c;预先按照 升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; …

刚刚:2023阿里云双十一优惠活动上线了!

2023阿里云双十一优惠活动「金秋云创季」开始啦&#xff0c;10月27日到10月31日可以领满减优惠&#xff0c;到11月1日和11月11日之间可以购买云服务器等产品&#xff0c;11.12到11.30日赢最高百万上云抵扣金&#xff0c;阿里云百科aliyunbaike.com分享2023阿里云双十一优惠活动…

Xray的简单使用

xray 简介 xray 是一款功能强大的安全评估工具&#xff0c;由多名经验丰富的一线安全从业者呕心打造而成&#xff0c;主要特性有: 检测速度快。发包速度快; 漏洞检测算法效率高。支持范围广。大至 OWASP Top 10 通用漏洞检测&#xff0c;小至各种 CMS 框架 POC&#xff0c;均…

前端实现打印功能Print.js

前端实现打印的方式有很多种&#xff0c;本人恰好经历了几个项目都涉及到了前端打印&#xff0c;目前较为推荐Print.js来实现前端打印 话不多说&#xff0c;直接上教程 官方链接: Print.js官网 在项目中如何下载Print.js 使用npm下载&#xff1a;npm install print-js --sav…

python 从mssql取出datetime2类型之后格式化

我mssql是datetime2类型&#xff0c;用df取出之后发现是个纳秒的int&#xff08;1698419713000000000 这种&#xff09; 所以格式化的话就需要变成秒为单位&#xff0c;他们之间是10的9次方倍。所以先除以1e9之后用datetime.datetime.fromtimestamp()转换之后再format就行了 l…

CCF CSP认证历年题目自练 Day39

题目 试题编号&#xff1a; 201312-5 试题名称&#xff1a; I’m stuck! 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   给定一个R行C列的地图&#xff0c;地图的每一个方格可能是’#‘, ‘’, ‘-’, ‘|’, ‘.’, ‘S’, ‘…

系列十九、循环依赖(一)

一、概述 循环依赖是指&#xff0c;多个bean之间相互依赖&#xff0c;形成了一个闭环。比如A依赖于B、B依赖于C、C依赖于A&#xff0c;形成了一个圈。 二、两种方式对循环依赖的影响 2.1、官网说明 2.2、结论 我们AB循环依赖问题只要A的注入方式是setter、并且是singleton&am…

Android14 WMS启动流程

一 概述 本文Android14源代码可参考&#xff1a;Search 在 Android 系统中&#xff0c;从设计的角度来看&#xff0c;窗口管理系统是基于 C/S 模式的。整个窗口系统分为服务端和客户端两大部分&#xff0c;客户端负责请求创建窗口和使用窗口&#xff0c;服务端完成窗口的维护…

智慧工地管理系统源码-数字孪生智慧工地可视化解决方案

一、智慧工地建设背景 我国经济发展正从传统粗放式的高速增长阶段&#xff0c;进入高效率、低成本、可持续的中高速增长阶段。随着现代建筑的复杂度和体量等不断增加&#xff0c;施工现场管理的内容越来越多&#xff0c;管理的技术难度和要求在不断提高。传统的施工现场管理模…

用超声波清洗机洗眼镜的有哪些?清洁力强的超声波清洗机不能错过

超声波清洗机在清洗眼镜方面表现出色&#xff0c;其强大的清洁能力可以彻底清除眼镜上的污垢和细菌。这种清洗方式被认为是一种高效且卫生的清洁方式&#xff0c;因为它利用高频振动和微射流打击力来清除污垢和细菌&#xff0c;而不是使用化学物质。对于那些长时间佩戴眼镜或者…

windows + ubuntu + vscode开发环境配置安装

一、卸载WSL/WSL2 如果安装了windows子系统的朋友&#xff0c;可以选择继续使用。或者提前卸载WSL&#xff0c;再选择安装虚拟机。虚拟机占用内存较大&#xff0c;WSL可能对于开发的一些需求还有欠缺。根据自己的实际情况进行选择。 WIN10/11安装WSL(请参考官方资料&#xff0c…

TSINGSEE青犀智慧仓储可视化视频智能监管系统方案

一、背景与需求 对于现在很多大型工厂或者物流基地来说&#xff0c;仓库无疑是存放物品的重点场所。仓储存放着大量货物&#xff0c;同时存在大量的辅助设备&#xff0c;需要进行全方位的监管&#xff0c;以避免发生安全事故&#xff0c;造成财产损失。原有的人工巡检方式已无…