Aspect实现接口调用频率限制

小灰灰 2023-07-18 15:30 7阅读 0赞

aop 的思想,就是讲方法外到内执行,中间给切成三段,未进入,进入,已退出

背景:

最近在做一个毕业设计,需要发送邮件(发送密码重置验证码),为了避免用户频繁调用邮件发送接口。
前端:将按钮置灰,开启倒计时,倒计时结束恢复按钮可用
由于没有登录,恶意的可能会使用代码去刷接口(在未进入时将其拦截处理
后端:
使用自定义注解+aop 通过用户ip 限制短时间内的访问次数

准备:

自定注解,可以配置多长时间内最多访问多少次
aspect:处理标注了自定义注解的参数,执行相关逻辑。

代码实现

注解:

  1. @Documented
  2. @Target({ ElementType.METHOD})
  3. @Retention(RetentionPolicy.RUNTIME)
  4. public @interface RequestFrequencyLimit {
  5. //访问时间间隔 默认是60 秒
  6. int interval() default 60000;
  7. //访问次数限制
  8. int count() default 3;//默认interval 时间内最多访问3次
  9. }

aspect:

  1. /** * 接口访问频率 限制aop */
  2. @Aspect
  3. @Component
  4. @Slf4j
  5. public class RequestFrequencyLimitAop {
  6. Map<String, RequestRecord> records = new ConcurrentHashMap<>();//由于是单例,需要注意线程安全,当然也可以使用redis 替代
  7. @Autowired
  8. HttpServletRequest request;
  9. @Pointcut("@annotation(top.forethought.orderfoodyoulike.aops.RequestFrequencyLimit)")
  10. public void requestLimit() {
  11. }
  12. @Around("requestLimit() && @annotation(requestFrequencyLimit)")
  13. public Object doAround(ProceedingJoinPoint joinPoint, RequestFrequencyLimit requestFrequencyLimit) throws Throwable {
  14. Object res = null;
  15. long now = System.currentTimeMillis();
  16. if (isNull(requestFrequencyLimit)) {
  17. return joinPoint.proceed();
  18. }
  19. //根据ip查找访问记录
  20. String clientIp = IpUtil.getIpAddress(request);
  21. RequestRecord requestRecord = records.get(clientIp);
  22. if (isNull(requestRecord) || now - requestRecord.firstRequestTime > requestFrequencyLimit.interval()) {
  23. requestRecord = new RequestRecord();
  24. requestRecord.firstRequestTime = now;
  25. requestRecord.requestCount = 1;
  26. } else {
  27. //更新访问次数
  28. requestRecord.requestCount++;
  29. }
  30. if (requestRecord.requestCount > requestFrequencyLimit.count()) {
  31. log.error("访问太过频繁,请稍后再试,ip={}", clientIp);
  32. throw GlobalException.builder().msg("访问太过频繁,请稍后再试").build();
  33. }
  34. //保存访问记录
  35. records.put(clientIp, requestRecord);
  36. return joinPoint.proceed();
  37. }
  38. class RequestRecord {
  39. int requestCount;//访问次数
  40. Long firstRequestTime;//第一次访问时间
  41. }
  42. }

使用效果:

在这里插入图片描述
60秒内同一个ip 最多访问该接口3次
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,7人围观)

还没有评论,来说两句吧...

相关阅读