场景解决方案
2025-01-22 08:19:30    261 字   
This post is also available in English and alternative languages.

1. 接口防刷

  1. 实现HandlerInterceptor接口,拦截所有(部分)接口。
  2. 通过 AOP 对所有(部分)接口实施切面拦截。

在拦截的逻辑中,获取到请求发起方的关键信息,如请求方IP、请求方MAC、请求的地址,将这些信息存储在 redis 中,设置对应的失效时间,以达到指定时间范围内防刷的目的。

  • 关于接口

    项目中并不是所有接口都需要防刷。

    建议使用自定义注解形式,在Controller类中标记需要防刷的接口(方法)。

  • 关于拦截方式

    • 实现HandlerInterceptor接口进行拦截

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      public class AccessLimintInterceptor implements HandlerInterceptor {

      @Resource
      private RedisTemplate redisTemplate;

      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
      if (!(handler instanceof HandlerMethod)) {
      return Boolean.TRUE;
      }

      HandlerMethod targetMethod = (HandlerMethod) handler;

      // 取出目标方法中的 AccessLimit 注解
      AccessLimit accessLimit = targetMethod.getMethodAnnotation(AccessLimit.class);
      if (Objects.isNull(accessLimit)) {
      return Boolean.TRUE;
      }

      // ...

      return Boolean.TRUE;
      }
      }
    • 通过 AOP 进行拦截

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      @Slf4j
      @Aspect
      @Component
      public class AccessLimitAspect {

      @Resource
      private RedisTemplate redisTemplate;

      @Before("@annotation(accessLimit)")
      public void before(JoinPoint joinPoint, AccessLimit accessLimit) {
      // ...
      }
      }