Spring boot 对接口限制IP访问次数
1、需要的依赖
<!-- redis依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- AOP依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!-- Map依赖 用redis就不需要了 --> <dependency> <groupId>net.jodah</groupId> <artifactId>expiringmap</artifactId> <version>0.5.8</version> </dependency>
2、定义注解
package org.springblade.modules.aspect.annotation; import java.lang.annotation.*; /** * 接口访问频率 * * @author * @date 2022/08/27 */ @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface InterfaceAccessRestriction { /** * 时间毫秒 单位:毫秒(默认:1分钟) * * @return long */ long time() default 60000; /** * 允许请求的次数 默认 30 * * @return int */ int value() default 30; }
3、切面实现
借助redis实现
package org.springblade.modules.aspect; import lombok.extern.slf4j.Slf4j; 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.springblade.core.tool.api.R; import org.springblade.core.tool.api.ResultCode; import org.springblade.modules.aspect.annotation.InterfaceAccessRestriction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.BoundHashOperations; import org.springframework.data.redis.core.StringRedisTemplate; 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; /** * 接口访问频率 * * @author matrix * @date 2022/08/27 */ @Aspect @Component @Slf4j public class InterfaceAccessRestrictionAspect { @Autowired private StringRedisTemplate redisTemplate; @Pointcut("@annotation(interfaceAccessRestriction)") public void controllerAspect(InterfaceAccessRestriction interfaceAccessRestriction) { } @Around(value = "controllerAspect(interfaceM)", argNames = "pjp,interfaceM") public Object doAround(ProceedingJoinPoint pjp, InterfaceAccessRestriction interfaceM) throws Throwable { //这里用的是 args[0] 作为key,正常场景可以用ip。 String key = String.valueOf(pjp.getArgs()[0]); RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes) ra; if (sra == null){ return pjp.proceed(); } HttpServletRequest request = sra.getRequest(); String requestUri = request.getRequestURI(); String remoteAddr = request.getRemoteAddr(); BoundHashOperations<String, Object, Object> bho = redisTemplate.boundHashOps("blade:interfaceAccessRestriction:" + key); String ipCnt = (String) bho.get(key); int uCount = ipCnt == null ? 0 : "".equals(ipCnt) ? 0 : Integer.parseInt(ipCnt); if (uCount >= interfaceM.value()) { log.error("接口拦截:{} 请求超过限制频率【{}次/{}ms】,参数key为{}", request.getRequestURI(), interfaceM.value(), interfaceM.time(), key); R<?> r = new R<>(); r.setCode(ResultCode.FAILURE.getCode()); r.setMsg("刷新频率过高,请" + bho.getExpire() + "秒后再操作"); return r; } else { bho.increment(key, 1); bho.expire(interfaceM.time(), TimeUnit.MILLISECONDS); } return pjp.proceed(); } }
4、使用
5、效果
再结合自己的需求改改吧。
借鉴博客:https://www.cnblogs.com/zys2019/p/16328053.html#_label0
内容仅供参考,并非百分百解决您的问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!