返回

巧用 AOP + Redis:轻松实现细粒度的接口访问限制

后端

引言

在微服务架构中,接口的安全性和可靠性至关重要。为了防止恶意攻击和滥用,需要对接口访问进行细粒度的控制。本文将介绍一种基于 AOP(面向切面编程)、Redis 和自定义注解的解决方案,帮助你轻松实现这一目标。

原理概述

AOP 是一种编程技术,允许我们以非侵入式的方式拦截和增强方法的执行。通过使用 AOP,我们可以定义切面(Aspect),在方法调用前后执行额外的操作。Redis 是一种分布式缓存,用于存储键值对数据,它非常适合存储接口访问频率等信息。自定义注解则用于标记需要限制访问的接口方法。

实现步骤

1. 创建自定义注解

首先,创建一个自定义注解,例如 @AccessLimit(count = 10, period = 60),其中 count 表示允许的访问次数,period 表示时间窗口(单位为秒)。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AccessLimit {
    int count() default 10;
    int period() default 60;
}

2. 编写 AOP 切面

接下来,编写一个 AOP 切面类,拦截所有标注了 @AccessLimit 注解的方法。在切面方法中,我们使用 Redis 存储每个接口的访问次数,并在达到限制时抛出异常。

@Aspect
@Order(1)
public class AccessLimitAspect {

    private final RedisTemplate<String, Integer> redisTemplate;

    public AccessLimitAspect(RedisTemplate<String, Integer> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    @Around("@annotation(accessLimit)")
    public Object around(ProceedingJoinPoint joinPoint, AccessLimit accessLimit) {
        String key = String.format("access_limit:%s:%s", joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
        Integer count = redisTemplate.opsForValue().get(key);
        if (count == null) {
            count = 0;
        }
        if (count >= accessLimit.count()) {
            throw new AccessLimitException("访问受限");
        }
        redisTemplate.opsForValue().set(key, ++count, accessLimit.period(), TimeUnit.SECONDS);
        return joinPoint.proceed();
    }
}

3. 集成到 Spring Boot 项目

在 Spring Boot 项目中,需要在配置类中启用 AOP 切面并注册 Redis bean。

@Configuration
public class ApplicationConfig {

    @Bean
    public AccessLimitAspect accessLimitAspect(RedisTemplate<String, Integer> redisTemplate) {
        return new AccessLimitAspect(redisTemplate);
    }

}

使用示例

在需要限制访问的接口方法上添加 @AccessLimit 注解即可。

@RestController
@RequestMapping("/api")
public class ExampleController {

    @GetMapping("/test")
    @AccessLimit(count = 10, period = 60)
    public String test() {
        return "访问成功";
    }
}

优点

  • 细粒度控制: 通过自定义注解,可以针对不同的接口方法设置不同的访问限制规则。
  • 分布式存储: 利用 Redis 存储访问次数,即使在分布式环境中也能保证一致性。
  • 非侵入式: AOP 切面以非侵入式的方式拦截方法,不会影响原有业务逻辑。
  • 代码重用: 将访问限制逻辑封装在一个独立的模块中,方便其他项目复用。

结论

通过使用 AOP + Redis + 自定义注解,我们可以轻松实现细粒度的接口访问限制,增强微服务应用的安全性。这种方法具有细粒度控制、分布式存储和非侵入式的优点,非常适合在需要对接口访问进行精细化管理的场景。