引言
随着互联网的快速发展,接口防刷(限流)成为了一个十分重要的安全措施。在SpringBoot中,我们可以通过定义拦截器、自定义注解和Redis来实现接口防刷功能。
什么是接口防刷(限流)?
接口防刷指的是对系统中的某个接口进行限制,防止用户在较短的时间内大量请求该接口,从而导致系统资源的浪费和性能下降。通过限制每个用户对某个接口的访问频率,可以有效控制系统的负载,并提高系统的稳定性和安全性。
实现步骤
1. 定义自定义注解
首先,我们需要定义一个自定义注解 @AccessLimit
,用来标注需要限流的接口方法。
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AccessLimit {
// 最大请求数量
int maxRequest() default 10;
// 限制周期(单位:秒)
int period() default 60;
}
2. 实现拦截器
接下来,我们需要实现一个拦截器 AccessLimitInterceptor
,用来对带有 @AccessLimit
注解的接口方法进行拦截。
public class AccessLimitInterceptor extends HandlerInterceptorAdapter {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 获取接口方法的注解信息
HandlerMethod handlerMethod = (HandlerMethod) handler;
AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
if (accessLimit != null) {
// 获取用户的IP地址和请求路径
String ip = getIpAddress(request);
String uri = request.getRequestURI();
// 生成访问限制的键名
String key = "access_limit:" + uri + ":" + ip;
// 获取限制周期和最大请求数量
int period = accessLimit.period();
int maxRequest = accessLimit.maxRequest();
// 判断是否超出限制
if (redisTemplate.hasKey(key)) {
int count = (int) redisTemplate.opsForValue().get(key);
if (count >= maxRequest) {
throw new RuntimeException("请求过于频繁,请稍后再试!");
} else {
redisTemplate.opsForValue().increment(key, 1);
}
} else {
redisTemplate.opsForValue().set(key, 1, period, TimeUnit.SECONDS);
}
}
return true;
}
// 获取客户端的IP地址
private String getIpAddress(HttpServletRequest request) {
String xForwardedForHeader = request.getHeader("X-Forwarded-For");
if (xForwardedForHeader == null) {
return request.getRemoteAddr();
} else {
// 多次反向代理后会有多个IP值,第一个非unknown的IP是真实IP
return xForwardedForHeader.split(",")[0].trim();
}
}
}
3. 注册拦截器
然后,我们需要在SpringBoot的配置文件中注册拦截器 AccessLimitInterceptor
。
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
@Autowired
private AccessLimitInterceptor accessLimitInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(accessLimitInterceptor);
}
}
4. 使用自定义注解
最后,我们可以在需要限流的接口方法上添加 @AccessLimit
注解。
@RestController
public class TestController {
@RequestMapping("/test")
@AccessLimit(maxRequest = 10, period = 60)
public String test() {
return "Hello World!";
}
}
总结
通过定义拦截器、自定义注解和Redis,我们可以很方便地实现接口防刷(限流)功能。这样可以有效避免用户对系统接口的过于频繁的请求,保障系统的稳定性和安全性。
希望本篇博客能帮助到你,如果有任何问题,请留言或者私信联系我。
谢谢阅读!
参考链接:SpringBoot定义拦截器+自定义注解+Redis实现接口防刷(限流)
本文来自极简博客,作者:闪耀之星喵,转载请注明原文链接:SpringBoot定义拦截器 自定义注解 Redis 实现接口防刷 (限流)