Spring Boot中通过HandlerInterceptor实现IP白名单与接口限流:preHandle校验真实IP(支持X-Forwarded-For)、匹配CIDR白名单;内存级计数器按路径/IP统计,超限返回429;注册时排除actuator等路径;分布式场景可选Redis+Redisson降级保障。

在 Java 的 Spring Boot 项目中,为 REST 接口配置拦截器实现 IP 白名单和接口防刷限流,核心思路是:通过 HandlerInterceptor 拦截请求,在 preHandle 方法中完成 IP 校验与访问频次控制。不依赖第三方组件也能快速落地,但结合 Redis 可提升限流的分布式可靠性。
定义拦截器实现 IP 白名单校验
创建自定义拦截器类,继承 HandlerInterceptor,在 preHandle 中获取客户端真实 IP 并比对白名单集合:
- 使用
request.getRemoteAddr()获取基础 IP;若服务前有 Nginx 或网关,需从X-Forwarded-For或X-Real-IP头中提取(注意防御伪造) - 白名单建议配置在
application.yml中,用@Value("${whitelist.ips:127.0.0.1,localhost}")注入并解析为Set<string></string> - 匹配时支持 CIDR(如
192.168.1.0/24)可引入Apache Commons Net的SubnetUtils辅助判断 - 校验失败直接返回
response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access denied"),不放行
集成简易令牌桶或计数器实现接口限流
单机限流可用 ConcurrentHashMap + AtomicInteger 实现内存级计数器,按“接口路径 + IP”或仅“接口路径”维度统计:
Java开发手册规约集合,基于阿里巴巴Java开发手册(嵩山版)。 涵盖7大维度:编程规约、异常日志、单元测试、安全规约、MySQL数据库、工程结构、设计规约。 当用户需要:(1) 编写或审查Java代码 (2) 检查命名/代码规范 (3) 处理异常和日志 (4) 编写单元测试 (5) 安全编码 (6) 数据库设...
- 构造 key 示例:
ip + ":" + request.getRequestURI()或request.getRequestURI() + ":global" - 设置窗口时间(如 60 秒)和最大请求数(如 100 次),用
System.currentTimeMillis()判断是否过期 - 每次请求原子递增计数,超限时返回
SC_TOO_MANY_REQUESTS (429),并添加Retry-After响应头 - 注意清理过期 key,避免内存泄漏;也可用 Guava Cache 自动过期
注册拦截器并排除放行路径
通过实现 WebMvcConfigurer 的 addInterceptors 方法注册拦截器,并明确指定需要保护的路径模式:
立即学习“Java免费学习笔记(深入)”;
- 拦截路径推荐使用
"/api/**"或具体 Controller 路径前缀,避免误拦静态资源、Swagger、健康检查等 - 调用
registry.excludePathPatterns("/actuator/**", "/swagger-ui/**", "/webjars/**")显式放行 - 若项目使用 WebFlux,需改用
WebFilter替代HandlerInterceptor
升级为分布式限流(可选)
当服务部署多实例时,内存计数器失效,建议接入 Redis 实现统一限流:
- 使用 Redis 的
INCR+EXPIRE组合模拟滑动窗口,key 设计为rate_limit:{ip}:{uri}:{window_start} - 更稳妥方案是用 Redisson 的
RRateLimiter,它封装了 Lua 脚本保证原子性,支持匀速/突发模式 - 注意 Redis 连接异常时应降级为本地限流或直接放行,避免雪崩

















