在互联网应用场景中,接口被恶意刷流量或攻击已成常态。尤其是在注册、登录、领取优惠券、秒杀抢购等核心接口上,如果缺乏有效的限流或防刷机制,轻则资源耗尽,重则服务宕机、数据泄露。
下文是SpringBoot 3 中 接口防刷的 8 大实战解决方案,助你轻松构建稳定、安全的微服务系统。
1. Nginx 级别限流(推荐作为第一道防线)
Nginx 限流模块(ngx_http_limit_req_module)可基于 IP 等维度进行请求限流,适用于静态资源、防止恶意爬虫。
配置示例:
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
server {
location /api/ {
limit_req zone=one burst=5 nodelay;
}
}
}
rate=10r/s
限速为每秒 10 次
burst=5
允许突发请求数为 5 个
nodelay
立即处理突发请求,不排队
优点: 性能高、配置简单
缺点: 粒度粗,不适用于用户维度
2. 基于拦截器+Redis 实现接口限流
核心思想:
通过 HandlerInterceptor 拦截请求,结合 Redis 计数器判断当前 IP/用户是否超过访问频率。
步骤:
自定义注解 @AccessLimit 配置时间窗口、最大次数
拦截器读取注解值,根据 key 计数
超出限制则返回错误
@AccessLimit(seconds = 60, maxCount = 10)
@GetMapping("/api/limit")
public String limitTest() {
return "请求成功";
}
String key = "access:" + ip + ":" + uri;
Long count = redisTemplate.opsForValue().increment(key);
优点: 灵活控制访问频率,可扩展维度(IP、用户)
缺点: 依赖 Redis,侵入代码
3. Google Guava + 本地缓存限流
使用 Guava 提供的 RateLimiter(令牌桶算法)快速实现限流,适合 单机应用场景。
RateLimiter rateLimiter = RateLimiter.create(5.0); // 每秒生成 5 个令牌
if (rateLimiter.tryAcquire()) {
// 允许访问
} else {
// 拒绝访问
}
优点: 无需依赖第三方服务
缺点: 无法集群共享数据
4. Sentinel 接口防刷利器(推荐)
阿里开源的 Sentinel 是一个功能强大且灵活的限流熔断组件,支持控制台可视化配置、动态扩展和多种限流策略。
常见限流维度:
- QPS(每秒请求数)限流
- 并发线程数限流
- 热点参数限流(针对热门资源限流)
- 关联限流(资源间依赖控制)
- 链路限流(不同入口资源独立统计)
引入依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
</dependency>
控制台部署(推荐配置持久化)
下载控制台 jar:
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -jar sentinel-dashboard.jar
注解式限流使用:
@SentinelResource(value = "hello", blockHandler = "handleBlock")
@GetMapping("/hello")
public String hello() {
return "Hello Sentinel";
}
public String handleBlock(BlockException ex) {
return "被限流了!";
}
编程式限流:
try (Entry entry = SphU.entry("order-service")) {
// 业务逻辑
} catch (BlockException ex) {
// 限流处理逻辑
}
高级玩法:
- 配合 Nacos 实现规则持久化
- 自定义资源路径解析器,按用户或 IP 限流
WebCallbackManager.setUrlCleaner(url -> {
// 统一 URL 资源名,避免 path 变量被当成不同资源
return url.replaceAll("/user/\\d+", "/user/*");
});
优点: 功能强大、集成简单、支持动态化
缺点: 依赖 Sentinel 控制台,需配置持久化规则
5. 验证码拦截(强验证方式防刷)
验证码机制适用于注册/登录等关键接口,阻止自动脚本攻击。
Easy-Captcha 使用示例:
添加依赖:
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
生成验证码:
@GetMapping("/captcha")
public void getCaptcha(HttpServletRequest request, HttpServletResponse response) throws IOException {
ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(150, 40, 4, 4);
String text = captcha.getCode();
String captchaId = UUID.randomUUID().toString();
redisTemplate.opsForValue().set("captcha:" + captchaId, text, 5, TimeUnit.MINUTES);
Cookie cookie = new Cookie("captchaId", captchaId);
response.addCookie(cookie);
response.setContentType("image/png");
captcha.write(response.getOutputStream());
}
登录时验证:
@PostMapping("/login")
public String login(@RequestParam String code, @CookieValue("captchaId") String captchaId) {
String redisCode = redisTemplate.opsForValue().get("captcha:" + captchaId);
if (!code.equalsIgnoreCase(redisCode)) {
throw new RuntimeException("验证码错误");
}
// 登录逻辑
}
优点: 防止脚本攻击,兼容用户行为分析
缺点: 用户体验稍差,不适合频繁调用接口
6. 接入滑块验证码/行为验证码(如腾讯滑块)
用于注册、投票等关键行为,需 JS SDK 支持,推荐服务:
极验(geetest)
腾讯云验证码(支持行为识别)
7. IP 白名单拦截机制
适用于对内系统、支付回调接口等,防止非授权来源访问。
示例:
List<String> whiteIps = Arrays.asList("127.0.0.1", "192.168.1.1");
if (!whiteIps.contains(request.getRemoteAddr())) {
response.setStatus(403);
response.getWriter().write("非法访问");
}
8. 用户行为分析+风控(智能防刷)
适用于大中型系统,配合日志采集系统(如 ELK)+ 用户行为画像 + 可疑行为预警。
异常行为:频繁点击、访问路径异常、接口秒级访问
数据支撑:埋点日志分析 + 机器学习模型判断
常见方案:
接入 OpenTelemetry / Skywalking 做链路追踪
建立行为模型识别“异常访问轨迹”
总结对比表:
结论
接口防刷并非“一劳永逸”,而是一个组合拳策略。应根据接口类型、业务场景、系统架构来灵活选择:
- 静态资源或统一入口 👉 Nginx 限流
- 核心接口 👉 Sentinel + 验证码/行为验证
- 数据支撑 👉 接入日志分析、构建风控体系