防护组件 (yudao-spring-boot-starter-protection)
引用文件
目录
简介
本文件面向 yudao-spring-boot-starter-protection 防护组件,系统化阐述以下能力与实现细节:
- 幂等性保护(IdempotentAspect):请求去重、重复提交防护、基于 Token 的并发控制
- 限流器(RateLimiterAspect):滑动窗口计数器算法、限流策略与 Redis 实现
- API 签名(ApiSignatureAspect):签名算法、时间戳验证、防重放攻击
- 分布式锁与接口防刷、恶意请求识别等安全防护特性
- 提供配置与使用示例,帮助在不同业务场景中选择合适的防护策略
项目结构
该组件以 Spring AOP 切面为核心,围绕注解驱动的拦截器组织功能模块,并通过 Redis 进行状态持久化与分布式协调。
图表来源
- IdempotentAspect.java
- RateLimiterAspect.java
- ApiSignatureAspect.java
- RedisDistributionLockUtils.java
章节来源
- IdempotentAspect.java
- RateLimiterAspect.java
- ApiSignatureAspect.java
- RedisDistributionLockUtils.java
核心组件
- 幂等性保护(IdempotentAspect):通过 Redis SET IF NOT EXIST 实现“令牌”锁定,避免同一请求在超时窗口内重复执行;支持异常时自动清理键,降低脏锁风险。
- 限流器(RateLimiterAspect):基于 Redis 的滑动窗口计数器,按固定时间窗口统计请求数量,超过阈值则拒绝。
- API 签名(ApiSignatureAspect):对请求参数、请求体、请求头进行规范化排序拼接后做 SHA-256 签名;结合时间戳容差与一次性随机数(nonce)防重放。
章节来源
架构总览
三类切面均采用注解驱动拦截目标方法,解析 Key 后委托各自的 DAO/工具完成原子性判断或状态维护,最终在命中策略时抛出统一错误码。
图表来源
组件详解
幂等性保护(IdempotentAspect)
- 核心思想:以“请求 Key”为维度,在指定超时时间内对同一请求进行“令牌”锁定,避免重复执行。
- 关键流程:
- 解析 Key(支持多种 KeyResolver)
- 使用 Redis SET IF NOT EXIST 原子设置键值(带过期时间)
- 若失败,视为重复请求,抛出统一错误码
- 正常执行业务;若发生异常且配置允许,删除 Key 防止脏锁
- 适用场景:下单、转账、扣款等高危操作;按钮重复点击;前端重试导致的重复提交
- 与分布式锁的关系:可配合 RedisDistributionLockUtils 实现更细粒度的资源互斥
图表来源
章节来源
限流器(RateLimiterAspect)
- 核心思想:基于滑动窗口计数器,统计固定时间窗口内的请求数,超过阈值则限流。
- 关键流程:
- 解析 Key(支持多种 KeyResolver)
- 调用 Redis DAO 执行“尝试获取配额”原子操作
- 失败则抛出统一错误码,提示请求过于频繁
- 适用场景:秒杀、大促活动、接口滥用防护、爬虫治理
- 策略建议:按接口维度、IP 维度、账号维度组合 Key;合理设置窗口大小与阈值
图表来源
章节来源
API 签名(ApiSignatureAspect)
- 核心思想:对请求参数、请求体、请求头进行规范化排序拼接后做 SHA-256 签名;结合时间戳容差与一次性随机数(nonce)抵御重放攻击。
- 关键流程:
- 校验请求头关键字段(appId、timestamp、nonce、sign),并检查时间戳偏差
- 校验 nonce 是否已在缓存中使用(一次性)
- 按约定规则构建签名字符串并计算哈希
- 通过后将 nonce 写入缓存并设置 TTL(通常为时间戳容差的两倍)
- 适用场景:开放平台、第三方集成、移动端 SDK、服务间鉴权
图表来源
章节来源
分布式锁、接口防刷、恶意请求识别
- 分布式锁:组件提供 Redis 分布式锁工具,支持尝试加锁与解锁,可用于更细粒度的资源互斥与竞态控制。
- 接口防刷:结合限流与签名,可对高频重复请求、重放攻击、伪造请求进行有效拦截。
- 恶意请求识别:通过 nonce 一次性机制、时间戳容差、签名一致性等多维校验,降低恶意请求成功率。
章节来源
依赖关系分析
- 组件耦合
- 幂等与限流均依赖 Redis 原子操作能力,通过 DAO 层抽象屏蔽具体实现
- 签名依赖 Redis 缓存 nonce,确保一次性使用
- 外部依赖
- Spring AOP、AspectJ、RedisTemplate
- 统一错误码与通用异常体系
- 潜在风险
- Key 解析策略不当可能导致误伤 或绕过
- Redis 可用性直接影响防护效果
图表来源
- IdempotentAspect.java
- RateLimiterAspect.java
- ApiSignatureAspect.java
- RedisDistributionLockUtils.java
章节来源
- IdempotentAspect.java
- RateLimiterAspect.java
- ApiSignatureAspect.java
- RedisDistributionLockUtils.java
性能与可扩展性
- Redis 原子操作具备高吞吐与低延迟特性,适合高并发场景
- Key 设计应尽量短小且唯一,避免热点 Key
- TTL 设置需平衡防护强度与内存占用
- 可扩展点:自定义 KeyResolver、替换 Redis DAO、引入本地缓存兜底
故障排查指南
- 幂等性误判
- 现象:正常请求被判定为重复
- 排查:确认 Key 解析是否稳定;检查超时时间是否过短;核对异常清理策略
- 限流误伤
- 现象:正常流量被限流
- 排查:调整窗口大小与阈值;区分接口/用户/IP 维度;评估并发峰值
- 签名失败
- 现象:签名一致但被拒绝
- 排查:nonce 是否已使用;时间戳是否超出容差;签名字符串构建规则是否一致
- Redis 不可用
- 现象:所有防护失效
- 排查:检查连接配置、网络、哨兵/集群状态;必要时降级放行或熔断
章节来源
结论
yudao-spring-boot-starter-protection 通过 注解驱动的 AOP 切面,将幂等、限流、签名三大安全能力以统一方式接入业务,配合 Redis 原子操作实现高可靠防护。合理设计 Key 与策略参数,可在保证用户体验的同时有效抵御重复提交、滥用与重放攻击。
附录:配置与使用示例
- 幂等性保护
- 在目标方法上添加幂等注解,配置 Key 解析器、超时时间与异常时是否删除 Key
- 场景:支付回调、订单创建、转账扣款
- 限流
- 在目标方法上添加限流注解,配置窗口大小、阈值与 Key 解析器
- 场景:秒杀、大促、接口滥用防护
- API 签名
- 在目标方法上添加签名注解,配置 appId/nonce/timestamp/sign 请求头名称与时间戳容差
- 场景:开放平台、第三方集成、移动端 SDK
章节来源