0


使用Spring Boot自定义注解 + AOP实现基于IP的接口限流和黑白名单

在这里插入图片描述

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》本专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
💕《Jenkins实战》专栏主要介绍Jenkins+Docker+Git+Maven的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~

使用 Spring Boot 自定义注解和AOP实现基于IP的接口限流和黑白名单

前言

在我们日常开发的项目中为了保证系统的稳定性,很多时候我们需要对系统做限流处理,它可以有效防止恶意请求对系统造成过载。常见的限流方案主要有:

  • 网关限流NGINXZuul 等 API 网关
  • 服务器端限流:服务端接口限流
  • 令牌桶算法:通过定期生成令牌放入桶中,请求需要消耗令牌才能通过
  • 熔断机制HystrixResilience4j

本文将详细介绍

Spring Boot

通过自定义注解和

AOP

(面向切面编程),实现基于

IP

的限流和黑白名单功能,包括如何使用

Redis

存储限流和黑名单信息。

项目初始化

首先,创建一个 Spring Boot 项目,并添加必要的依赖。在 pom.xml 文件中添加以下内容:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency></dependencies>

配置

application.yml

加入

redis

配置

spring:#redisredis:# 地址host: 127.0.0.1
        # 端口,默认为6379port:6379

自定义限流注解

创建一个自定义注解

RateLimit

importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)public@interfaceRateLimit{//限制次数intlimit()default5;//限制时间 秒inttimeout()default60;}

编写限流切面

使用

AOP

实现限流逻辑,并增加

IP

黑白名单判断 , 使用

Redis

来存储和检查请求次数及黑名单信息。

importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.StringRedisTemplate;importorg.springframework.stereotype.Component;importjavax.servlet.http.HttpServletRequest;importjava.util.concurrent.TimeUnit;@Aspect@ComponentpublicclassRateLimitAspect{@AutowiredprivateStringRedisTemplate redisTemplate;@AutowiredprivateHttpServletRequest request;//定义黑名单key前缀privatestaticfinalStringBLACKLIST_KEY_PREFIX="blacklist:";//定义白名单key前缀privatestaticfinalStringWHITELIST_KEY_PREFIX="whitelist:";@Around("@annotation(rateLimit)")publicObjectrateLimit(ProceedingJoinPoint joinPoint,RateLimit rateLimit)throwsThrowable{//获取IPString ip = request.getRemoteAddr();//黑名单则直接异常if(isBlacklisted(ip)){thrownewRuntimeException("超出访问限制已加入黑名单,1小时后再访问");}//如果是白名单下的不做限制if(isWhitelisted(ip)){return joinPoint.proceed();}String key =generateKey(joinPoint, ip);int limit = rateLimit.limit();int timeout = rateLimit.timeout();String countStr = redisTemplate.opsForValue().get(key);int count = countStr ==null?0:Integer.parseInt(countStr);if(count < limit){
            redisTemplate.opsForValue().set(key,String.valueOf(count +1), timeout,TimeUnit.SECONDS);return joinPoint.proceed();}else{addToBlacklist(ip);thrownewRuntimeException("超出请求限制IP已被列入黑名单");}}privatebooleanisBlacklisted(String ip){return redisTemplate.hasKey(BLACKLIST_KEY_PREFIX+ ip);}privatebooleanisWhitelisted(String ip){return redisTemplate.hasKey(WHITELIST_KEY_PREFIX+ ip);}privatevoidaddToBlacklist(String ip){
        redisTemplate.opsForValue().set(BLACKLIST_KEY_PREFIX+ ip,"true",1,TimeUnit.HOURS);}privateStringgenerateKey(ProceedingJoinPoint joinPoint,String ip){String methodName = joinPoint.getSignature().getName();String className = joinPoint.getTarget().getClass().getName();return className +":"+ methodName +":"+ ip;}}

Controller中使用限流注解

创建一个简单的限流测试Controller,并在需要限流的方法上使用

@RateLimit

注解:,需要编写异常处理,返回

RateLimitAspect

异常信息,并以字符串形式返回

importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RestController@RequestMapping("/api")publicclassTestController{//由于是简单的测试项目,这里就直接定义异常处理,并为采用全局异常处理@ExceptionHandler(value =Exception.class)publicStringhandleException(Exception ex){return ex.getMessage();}@RateLimit(limit =5, timeout =60)@GetMapping("/limit")publicStringtestRateLimit(){return"Request successful!";}}

接口测试

使用接口调试工具,请求接口测试,博主这里使用的是

Apifox

,我们60秒内请求5次
前5次均返回

Request successful!

第6次会提示

超出请求限制IP已被列入黑名单

在这里插入图片描述

结语

通过以上步骤,我们成功地使用自定义注解和 AOP 实现了基于 IP 的接口限流和黑白名单功能。这种方法不仅简化了限流逻辑的实现,还增强了系统的安全性和稳定性。小伙伴们可以根据实际需求对限流逻辑进行进一步扩展和优化,例如增加不同的限流策略、动态调整限流参数等。


在这里插入图片描述


本文转载自: https://blog.csdn.net/lhmyy521125/article/details/139338340
版权归原作者 Micro麦可乐 所有, 如有侵权,请联系我们删除。

“使用Spring Boot自定义注解 + AOP实现基于IP的接口限流和黑白名单”的评论:

还没有评论