22 KiB
22 KiB
API安全防护
**本文引用的文件** - [ApiSignatureAspect.java](file://viewsh-framework/viewsh-spring-boot-starter-protection/src/main/java/com/viewsh/framework/signature/core/aop/ApiSignatureAspect.java) - [ApiSignature.java](file://viewsh-framework/viewsh-spring-boot-starter-protection/src/main/java/com/viewsh/framework/signature/core/annotation/ApiSignature.java) - [ViewshApiSignatureAutoConfiguration.java](file://viewsh-framework/viewsh-spring-boot-starter-protection/src/main/java/com/viewsh/framework/signature/config/ViewshApiSignatureAutoConfiguration.java) - [RateLimiterAspect.java](file://viewsh-framework/viewsh-spring-boot-starter-protection/src/main/java/com/viewsh/framework/ratelimiter/core/aop/RateLimiterAspect.java) - [RateLimiter.java](file://viewsh-framework/viewsh-spring-boot-starter-protection/src/main/java/com/viewsh/framework/ratelimiter/core/annotation/RateLimiter.java) - [IdempotentAspect.java](file://viewsh-framework/viewsh-spring-boot-starter-protection/src/main/java/com/viewsh/framework/idempotent/core/aop/IdempotentAspect.java) - [Idempotent.java](file://viewsh-framework/viewsh-spring-boot-starter-protection/src/main/java/com/viewsh/framework/idempotent/core/annotation/Idempotent.java) - [ViewshSecurityAutoConfiguration.java](file://viewsh-framework/viewsh-spring-boot-starter-security/src/main/java/com/viewsh/framework/security/config/ViewshSecurityAutoConfiguration.java) - [LogRecordServiceImpl.java](file://viewsh-framework/viewsh-spring-boot-starter-security/src/main/java/com/viewsh/framework/operatelog/core/service/LogRecordServiceImpl.java) - [ApiSignatureTest.java](file://viewsh-framework/viewsh-spring-boot-starter-protection/src/test/java/com/viewsh/framework/signature/core/ApiSignatureTest.java)目录
引言
本文件面向AIOT平台云项目的API安全防护,系统化梳理请求验证机制、频率限制、防重放攻击、API日志记录与审计、以及注入攻击防护策略,并提供可落地的配置与规则示例,帮助开发者在不牺牲易用性的前提下,构建高可靠、可运维的API安全体系。
项目结构
本项目围绕“保护”与“安全”两大框架模块提供API安全能力:
- 视图框架保护模块(viewsh-spring-boot-starter-protection):提供签名验证、限流、幂等控制等横切能力。
- 视图框架安全模块(viewsh-spring-boot-starter-security):提供认证授权、全局异常处理、操作日志审计等安全基础能力。
graph TB
subgraph "保护框架"
SIG["签名验证<br/>ApiSignatureAspect"]
RL["频率限制<br/>RateLimiterAspect"]
IDE["幂等控制<br/>IdempotentAspect"]
end
subgraph "安全框架"
SEC["安全自动配置<br/>ViewshSecurityAutoConfiguration"]
LOG["操作日志<br/>LogRecordServiceImpl"]
end
CLI["客户端"] --> SIG
CLI --> RL
CLI --> IDE
SIG --> SEC
RL --> SEC
IDE --> SEC
SEC --> LOG
图表来源
- ApiSignatureAspect.java
- RateLimiterAspect.java
- IdempotentAspect.java
- ViewshSecurityAutoConfiguration.java
- LogRecordServiceImpl.java
章节来源
核心组件
- 请求签名验证:基于注解拦截器,对请求头参数进行非空与时效校验,生成并比对签名,同时利用Redis记录nonce以抵御重放。
- 频率限制:支持多种Key解析器(默认/用户/IP/节点/SpEL),基于Redis实现滑动窗口风格的限流。
- 幂等控制:通过Redis SET IF ABSENT实现分布式锁,避免同一请求重复执行。
- 安全与日志:统一的认证入口、异常处理与操作日志记录,便于审计与追踪。
章节来源
- ApiSignature.java
- RateLimiter.java
- Idempotent.java
- ViewshSecurityAutoConfiguration.java
- LogRecordServiceImpl.java
架构总览
下图展示API请求在进入业务控制器前的关键安全拦截链路与职责分工:
sequenceDiagram
participant C as "客户端"
participant G as "网关/应用"
participant S as "签名拦截器<br/>ApiSignatureAspect"
participant R as "限流拦截器<br/>RateLimiterAspect"
participant I as "幂等拦截器<br/>IdempotentAspect"
participant B as "业务控制器"
participant L as "操作日志<br/>LogRecordServiceImpl"
C->>G : "HTTP 请求"
G->>S : "进入签名验证"
S-->>G : "通过/拒绝"
G->>R : "进入频率限制"
R-->>G : "通过/拒绝"
G->>I : "进入幂等控制"
I-->>G : "通过/拒绝"
G->>B : "执行业务逻辑"
B-->>G : "返回结果"
G->>L : "异步记录操作日志"
L-->>G : "完成"
G-->>C : "HTTP 响应"
图表来源
详细组件分析
请求签名验证(防重放与请求完整性)
- 核心流程
- 请求头参数校验:appId、timestamp、nonce、sign均不能为空;nonce长度不少于10位;timestamp与当前时间偏差不超过timeout。
- 签名生成与比对:按固定顺序拼接请求参数、请求体、请求头与密钥,计算摘要并与客户端传入签名比对。
- 防重放:将nonce写入Redis并设置TTL,TTL建议为允许时间差的两倍,确保nonce只被使用一次。
- 关键点
- appId对应appSecret由Redis DAO加载,缺失时直接拒绝。
- 失败时返回明确错误码,避免泄露内部细节。
- 配置要点
- timeout与timeUnit用于控制允许的时间漂移窗口。
- 可自定义请求头字段名(appId、timestamp、nonce、sign)以适配不同客户端。
- 常见问题
- nonce未设置或过短导致校验失败。
- timestamp格式非法或超窗导致拒绝。
- 签名算法不一致导致比对失败。
flowchart TD
Start(["进入签名验证"]) --> H1["校验请求头参数<br/>appId/timestamp/nonce/sign"]
H1 --> H2{"参数合法?"}
H2 -- 否 --> Fail["拒绝请求"]
H2 -- 是 --> S1["加载appSecret"]
S1 --> S2["生成服务端签名字符串"]
S2 --> S3["计算摘要并与客户端签名比对"]
S3 --> S4{"签名一致?"}
S4 -- 否 --> Fail
S4 -- 是 --> N1["写入nonce到Redis<br/>TTL=timeout*2"]
N1 --> N2{"写入成功?"}
N2 -- 否 --> Repeated["重复请求,拒绝"]
N2 -- 是 --> Pass["通过"]
图表来源
章节来源
- ApiSignatureAspect.java
- ApiSignature.java
- ViewshApiSignatureAutoConfiguration.java
- ApiSignatureTest.java
频率限制(滑动窗口与分布式限流)
- 核心流程
- 通过Key解析器生成限流Key(默认/用户/IP/节点/SpEL表达式)。
- 使用Redis尝试获取令牌(滑动窗口风格),若失败则触发限流异常。
- Key解析器
- 默认:全局限流。
- 用户:按用户维度限流。
- 客户端IP:按来源IP限流。
- 服务器节点:按节点维度限流。
- SpEL表达式:按动态表达式生成Key。
- 配置要点
- time与timeUnit定义统计周期。
- count定义周期内允许的最大请求数。
- keyResolver与keyArg决定限流粒度与表达式。
classDiagram
class RateLimiter {
+int time
+TimeUnit timeUnit
+int count
+String message
+Class~RateLimiterKeyResolver~ keyResolver
+String keyArg
}
class RateLimiterAspect {
+beforePointCut(joinPoint, rateLimiter)
}
RateLimiterAspect --> RateLimiter : "读取注解配置"
图表来源
章节来源
幂等控制(防重复提交)
- 核心流程
- 通过Key解析器生成幂等Key(默认/用户/SpEL表达式)。
- 使用Redis SET IF ABSENT加分布式锁,若失败则判定为重复请求。
- 正常执行后释放锁;异常时可按配置删除Key,避免阻塞后续请求。
- 配置要点
- timeout与timeUnit控制锁持有时间。
- deleteKeyWhenException控制异常时是否删除Key。
- keyResolver与keyArg决定幂等粒度。
flowchart TD
A["进入幂等拦截"] --> K["解析Key"]
K --> L["SET IF ABSENT加锁"]
L --> L1{"加锁成功?"}
L1 -- 否 --> E["重复请求,拒绝"]
L1 -- 是 --> X["执行业务逻辑"]
X --> X1{"执行成功?"}
X1 -- 是 --> U["释放锁"]
X1 -- 否 --> D{"异常删除Key?"}
D -- 是 --> R["删除Key"]
D -- 否 --> T["保留Key"]
U --> Z["返回结果"]
R --> Z
T --> Z
图表来源
章节来源
API日志记录与审计
- 日志内容
- 请求链路追踪ID、用户信息(登录态)、请求方法、URL、客户端IP、UA等。
- 操作类型、子类型、业务编号、动作描述与扩展字段。
- 异步记录
- 通过异步方式落库,避免阻塞主请求路径。
- 异常时记录错误日志,便于定位问题。
- 审计价值
- 支持事后审计、合规追溯与问题复盘。
sequenceDiagram
participant B as "业务层"
participant L as "日志服务<br/>LogRecordServiceImpl"
participant API as "操作日志API"
B->>L : "记录操作日志"
L->>L : "填充追踪ID/用户/请求信息"
L->>API : "异步创建操作日志"
API-->>L : "完成"
L-->>B : "返回"
图表来源
章节来源
安全配置与自动装配
- 安全自动配置
- 提供认证入口、权限不足处理、密码加密器、Token认证过滤器、安全上下文策略等。
- 签名自动配置
- 注册签名拦截器与Redis DAO,依赖Redis自动装配。
章节来源
依赖分析
- 组件耦合
- 签名/限流/幂等均通过AOP拦截器接入,与业务方法解耦。
- Redis DAO负责底层存储,Key解析器提供灵活的限流/幂等粒度。
- 外部依赖
- Redis:签名nonce、限流令牌、幂等锁均依赖Redis。
- Spring Security:提供认证授权基础设施。
- 潜在风险
- Redis不可用将影响所有保护能力。
- Key解析不当可能导致限流/幂等粒度过粗或过细。
graph LR
ASPECT_SIG["签名拦截器"] --> DAO_SIG["签名Redis DAO"]
ASPECT_RL["限流拦截器"] --> DAO_RL["限流Redis DAO"]
ASPECT_IDE["幂等拦截器"] --> DAO_IDE["幂等Redis DAO"]
SEC_AUTO["安全自动配置"] --> FILTER["Token认证过滤器"]
SIG_AUTO["签名自动配置"] --> ASPECT_SIG
图表来源
- ApiSignatureAspect.java
- RateLimiterAspect.java
- IdempotentAspect.java
- ViewshApiSignatureAutoConfiguration.java
- ViewshSecurityAutoConfiguration.java
性能考虑
- Redis热点
- 高频限流/幂等/签名nonce可能形成热点,建议:
- 合理设置Key TTL与统计周期,避免长期占用。
- 使用更细粒度的Key(如用户/IP/节点)降低单Key压力。
- 高频限流/幂等/签名nonce可能形成热点,建议:
- 异步日志
- 操作日志采用异步写入,减少对主请求的影响。
- AOP开销
- 注解拦截器在请求链路中增加少量开销,建议在高频接口上按需启用。
故障排查指南
- 签名失败
- 检查请求头字段是否齐全、nonce长度是否满足要求、timestamp是否在允许范围内。
- 确认服务端与客户端使用的签名算法一致。
- 核对appId对应的appSecret是否正确配置。
- 重复请求/重放
- 检查nonce是否已存在于Redis且未过期。
- 确认nonce的TTL是否覆盖允许的时间漂移范围。
- 请求过快
- 调整count与time参数,或切换更细粒度的Key解析器。
- 检查是否存在突发流量导致的瞬时峰值。
- 幂等冲突
- 检查timeout是否过短导致业务未完成即释放锁。
- 若异常删除Key策略开启,确认业务异常时Key已被清理。
- 日志未记录
- 检查异步线程池与网络调用是否正常。
- 关注异常日志输出,定位具体失败原因。
章节来源
结论
通过签名验证、限流、幂等控制与操作日志的协同,本项目在不侵入业务的前提下提供了完善的API安全防护能力。结合合理的配置与监控告警,可在保证用户体验的同时显著提升系统的抗攻击能力与可审计性。
附录
配置与规则示例
- 签名验证
- 在接口上添加签名注解,设置timeout与timeUnit以匹配业务时延;自定义请求头字段名以适配客户端。
- 示例路径参考:ApiSignature.java
- 频率限制
- 选择合适的Key解析器(默认/用户/IP/节点/SpEL),调整count与time参数。
- 示例路径参考:RateLimiter.java
- 幂等控制
- 根据业务需求选择Key解析器,设置timeout与deleteKeyWhenException。
- 示例路径参考:Idempotent.java
- 安全与日志
- 启用安全自动配置与操作日志记录,确保认证、异常处理与审计完备。
- 示例路径参考:ViewshSecurityAutoConfiguration.java,LogRecordServiceImpl.java
常见攻击场景与应对
- 参数篡改与重放
- 通过签名验证与nonce防重放机制抵御。
- 参考:ApiSignatureAspect.java
- 高频刷量
- 使用限流拦截器,按用户/IP/节点等维度精细化限流。
- 参考:RateLimiterAspect.java
- 重复提交
- 使用幂等拦截器,避免同一请求多次执行造成副作用。
- 参考:IdempotentAspect.java
- SQL注入/XSS/命令注入
- 本仓库未提供专门的注入防护组件。建议在输入参数校验、数据库访问层与前端渲染层分别实施:
- 输入参数校验:使用参数校验框架与白名单策略。
- SQL访问:使用ORM映射与参数化查询,避免动态拼接。
- XSS:对输出进行HTML转义与CSP策略。
- 命令注入:禁止动态执行外部命令,使用沙箱或受控接口。
- 参考:通用安全实践与参数校验组件(本仓库未提供专用注入防护模块)。
- 本仓库未提供专门的注入防护组件。建议在输入参数校验、数据库访问层与前端渲染层分别实施: