SpringAOP+自定义注解实现限制接口访问频率,利用滑动窗口思想Redis的ZSet(附带整个Demo)

目录

1.创建切面

2.创建自定义注解

3.自定义异常类

4.全局异常捕获

5.Controller层

 


demo的地址,自行获取《《——————————————————————————

Spring Boot整合Aop面向切面编程实现权限校验,SpringAop+自定义注解+自定义异常+全局异常捕获,实现权限验证,要求对每个接口都实现单独的权限校验

Spring Boot整合Aop面向切面编程实现权限校验,SpringAop+自定义注解+自定义异常+全局异常捕获,实现权限验证,要求对每个接口都实现单独的权限校验

背景

在日常开发中,为了保证系统稳定性,防止被恶意攻击,我们可以控制用户访问接口的频率,

 颜色部分表示窗口大小

在指定时间内,只能允许访问N次,我们将这个指定时间T,看出一个滑动的窗口宽度,Redis的zset的score为滑动窗口,在操作zset的时候,只保留窗口数据,删除其他数据

1.创建切面

package com.example.aspect;import com.example.annotation.RequestLimiting;
import com.example.exception.ConditionException;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;@Aspect
@Slf4j
@Component
public class ApiLimitedRoleAspect {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Pointcut("@annotation(com.example.annotation.RequestLimiting)")public void poincut() {}@Around("poincut() && @annotation(requestLimiting)")public Object doAround(ProceedingJoinPoint proceedingJoinPoint, RequestLimiting requestLimiting) throws Throwable {//获取注解参数long period = requestLimiting.period();long count = requestLimiting.count();ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();//获取ip和urlString ip = request.getRemoteAddr();String uri = request.getRequestURI();//拼接redis的key值String key = "reqLimiting" + uri + ip;ZSetOperations<String, String> zSetOperations = stringRedisTemplate.opsForZSet();//获取当前时间long curTime = System.currentTimeMillis();//添加当前时间zSetOperations.add(key, String.valueOf(curTime), curTime);//设置过期时间stringRedisTemplate.expire(key, period, TimeUnit.SECONDS);//删除窗口之外的值//这个a指的是实际窗口的范围边界,比如,我从10:00开始访问,//每秒访问1次,在11:12时,记录里就会有62条,此时的a表示10:12,//最后会删除掉10:00-10:12的所有key,留下的都10:12-11:12的keyLong a = curTime - period * 1000;log.error(String.valueOf(a));zSetOperations.removeRangeByScore(key, 0, a);//设置访问次数Long acount = zSetOperations.zCard(key);if (acount > count) {log.error("接口拦截:{}请求超过限制频率{}次/{}s,ip为{}", uri, count, period, ip);throw new ConditionException("10004", "接口访问受限,请稍后");}return proceedingJoinPoint.proceed();}}

2.创建自定义注解

package com.example.annotation;import java.lang.annotation.*;/**
*<p> </p>
*自定义注解* 接口访问频率
*@author panwu
*@descripion
*@date 2024/3/24 13:23
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLimiting {//窗口宽度long period() default  60;//允许访问次数long count() default  5;
}

 3.自定义异常类

package com.example.exception;public class ConditionException extends RuntimeException {private static final long serialVersionUID = 1L;private String code;//    public ConditionException(ConditionExceptionEnum conditionExceptionEnum){
//        super(conditionExceptionEnum.getDesc());
//        this.code = conditionExceptionEnum.getCode();
//    }public ConditionException(String code, String name) {super(name);this.code = code;}public ConditionException(String name){super(name);code="500";}public String getCode() {return code;}public void setCode(String code) {this.code = code;}}

4.全局异常捕获

package com.example.exception;import com.example.dto.Result;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ComonGlobalExceptionHandler {@ExceptionHandler(value = ConditionException.class)@ResponseBodypublic Result conditionException(ConditionException e){return Result.fail(e.getCode(),e.getMessage());}
}

5.Controller层

package com.example.controller;import com.example.annotation.RequestLimiting;
import com.example.dto.Result;
import lombok.extern.log4j.Log4j;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {@GetMapping()@RequestLimiting(count = 3)public Result get(){log.debug("访问成功");return Result.ok("访问成功");}
}

要知道的是,该Demo实现的是对同一用户的反复点击进行频率限制,也可用作幂等性校验,具体值需要设置,还需要考虑分布式情况,加上分布式锁

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

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

相关文章

WordPress分页函数function

1、可以通过下面的代码在编辑器上添加一个分页符按钮。 2、将下面的代码添加到当前主题functions.php即可。 3、代码如下&#xff1a; function mce_page_break($mce_buttons) { $pos array_search(wp_more, $mce_buttons, true); if ($pos ! false) { $buttons …

全球最强开源AI大模型来了!Databricks称DBRX吊打Llama 2和GPT-3.5

美国AI初创公司Databricks公布&#xff0c;在语言理解、编程和数学方面&#xff0c;其将开源的模型DBRX的测试得分均高于GPT-3.5、Mixtral、Meta的Llama 2-70B、马斯克旗下xAI的Grok-1。作为混合专家模型&#xff0c;DBRX的输出token速度高Llama 2一筹。 全球最强大的开源人工智…

车载以太网AVB交换机 gptp透明时钟 5口 全千兆 SW1500

全千兆车载以太网交换机 一、产品简要分析 5端口千兆车载以太网交换机&#xff0c;包含4个通道的1000BASE-T1接口使用罗森博格H-MTD和泰科MATEnet双接口&#xff0c;1个通道1000BASE-T标准以太网(RJ45接口)&#xff0c;可以实现车载以太网多通道交换&#xff0c;千兆和百兆车载…

Docker搭建LNMP环境实战(06):Docker及Docker-compose常用命令

Docker搭建LNMP环境实战&#xff08;06&#xff09;&#xff1a;Docker及Docker-compose常用命令 此处列举了docker及docker-compose的常用命令&#xff0c;一方面可以做个了解&#xff0c;另一方面可以在需要的时候进行查阅。不一定要强行记忆&#xff0c;用多了就熟悉了。 1、…

Golang hash/crc32 库实战指南:从基础到优化

Golang hash/crc32 库实战指南&#xff1a;从基础到优化 引言理解CRC32hash/crc32库概览实战技巧数据校验性能优化多线程应用 错误处理与调试错误处理调试 实际案例分析结论 总结重点回顾 引言 在现代软件开发中&#xff0c;数据的完整性和安全性至关重要。无论是数据库存储、…

Vue-vue3

一、Vue3简介二、Vue3有那些优化性能的提升源码升级拥抱TypeScript新的特性 三、创建Vue3.0工程四、Vue3工程结构&#xff08;使用cli创建的vue3&#xff09;五、常用的Composition API&#xff08;组合式API&#xff09;setupsetup的两个注意点 ref函数reactive函数Vue3.0中的…

PCL 彩色点云RGB转灰度并显示

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、原理概述 不同要素之间的灰度差异较为明显。点云灰度值与RGB属性的关系为:

MySQL高阶SQL语句(二)

文章目录 MySQL高阶SQL语句&#xff08;二&#xff09;一、MySQL常用查询1、子查询1.1 语法1.1.1 结合select语句查询1.1.2 结合insert语句查询1.1.3 结合update语句查询1.1.4 结合delete语句查询1.1.5 在in前面添加not1.1.6 exists关键字 2、别名 二、MySQL视图1、视图介绍1.1…

《科学技术创新》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答&#xff1a; 问&#xff1a;《科学技术创新》期刊是哪个级别&#xff1f; 答&#xff1a;省级 主管单位&#xff1a;黑龙江省科学技术协会 主办单位&#xff1a;黑龙江省科普事业中心 问&#xff1a;《科学技术创新》期刊影响因子&#xff1f; 答&#xff1a;(2…

bugku-web-Flask_FileUpload

查看页面源码 这里提示给他一个文件&#xff0c;它将返回一个python运行结果给我&#xff0c;并且提示只能上传jpg和png文件 传递一个图片 查看源码 传递一个非图片 将源码写入新建的txt文件中 print(hello world) 将文件后缀改为jpg 上传 上传成功 查看源码 得到运行结果 我…

展示大屏-24小时天气预报

一、项目说明 展示大屏显示未来一周天气和24小时天气详情。 二、技术工具 1.语言&框架&#xff1a;java、springboot 2.UI界面&#xff1a;jQuery、HTML、CSS、 VUE 3.开发工具&#xff1a;IntelliJ IDEA、Eclipse 三、实现步骤 后端步骤 1.调取免费或收费的API接口。 …

JAVA面试大全之并发篇

目录 1、并发基础 1.1、多线程的出现是要解决什么问题的? 本质什么? 1.2、Java是怎么解决并发问题的? 1.3、线程安全有哪些实现思路? 1.4、如何理解并发和并行的区别? 1.5、线程有哪几种状态? 分别说明从一种状态到另一种状态转变有哪些方式? 1.6、通常线程有哪几…

mysql数据库高级面试题-2024

数据库三大范式是什么 第一范式&#xff1a;列不可再分 第二范式&#xff1a;行可以唯一区分&#xff0c;主键约束&#xff0c;要求表中的每个非主键列完全依赖于主键列 第三范式&#xff1a;表的非主属性不能依赖与其他表的非主属性 外键约束 且三大范式是一级一级…

「DevExpress中文教程」如何将DevExtreme JS HTML编辑器集成到WinForms应用

在本文中我们将演示一个混合实现&#xff1a;如何将web UI工具集成到WinForms桌面应用程序中。具体来说&#xff0c;我们将把DevExtreme JavaScript WYSIWYG HTML编辑器(作为DevExtreme UI组件套件的一部分发布的组件)集成到Windows Forms应用程序中。 获取DevExtreme v23.2正式…

2024最新版克魔助手抓包教程(9) - 克魔助手 IOS 数据抓包

引言 在移动应用程序的开发中&#xff0c;了解应用程序的网络通信是至关重要的。数据抓包是一种很好的方法&#xff0c;可以让我们分析应用程序的网络请求和响应&#xff0c;了解应用程序的网络操作情况。克魔助手是一款非常强大的抓包工具&#xff0c;可以帮助我们在 Android …

远程todesk 和向日葵连接ubuntu无法连接

问题 今天远程用todesk 和向日葵连接对方ubuntu22.04 LTS的 电脑&#xff0c;无法连接&#xff0c;一开始以为是防火墙问题&#xff0c;后来发现不是&#xff0c;找了半天资料最后解决。 原因 没有安装X11桌面环境&#xff0c;还是原先的wayland 解决方案 ctrl alt T …

华为耳机快速配对新设备,一招搞定

耳机现在已经是我们形影不离的随身设备&#xff0c;如果我们碰见华为手机或平板无法连接或连接不上华为耳机&#xff08;如FreeBuds、FreeLace系列及FreeClip蓝牙耳机&#xff09;的问题&#xff0c;其实很简单&#xff0c;今天分享一个小妙招&#xff0c;帮助我们快速解决这个…

搭建机器人产业发展重要展示平台“2024南京国际机器人展览会”

2024南京国际智能机器人展览会 2024 Nanjing Intelligent Robot Expo 时间:2024年11月22-24日 地点:南京国际博览中心 南京&#xff0c;这座历史悠久的文化名城&#xff0c;如今正站在机器人产业发展的前沿。随着全球科技的飞速进步&#xff0c;机器人产业已经成为推动经济社…

C 语言贪吃蛇源码解析

贪吃蛇是一款经典的电子游戏&#xff0c;玩家控制一条不断成长的蛇&#xff0c;需要避免撞到自己的身体或者游戏边界&#xff0c;同时吃掉出现在屏幕上的食物以增长身体长度。 下面是一个简单的贪吃蛇游戏的C语言实现&#xff0c;使用了标准输入输出库conio.h和时间库windows.h…

C语言二叉树和堆(个人笔记)

二叉树和堆 二叉树1二叉树的概念和结构1.1特殊的二叉树1.2二叉树的性质&#xff08;规定根节点的层数为1&#xff09;1.3二叉树的存储结构 2.二叉树的顺序结构和实现2.1二叉树的顺序结构2.2堆的概念和结构2.3堆的实现2.4堆的应用2.4.1堆排序 2.5TOP-K问题 3.二叉树的遍历4.二叉…