> 状态(2026-04-18 立项):**提案阶段,未实施** > 优先级:高(Phase B.2 基座安全增强,早于 mjava-com 专项) ## Why mjava 基座当前 API 安全裸奔: - **无统一鉴权**:任何知道 URL 的调用方都能直接访问任意 Controller(`filter/RequestFilter` 和 `RequestInterceptor` 当前只打日志,不做任何校验) - **无防重放保护**:即便将来加签名,不带时间窗 + Nonce 的话攻击者仍可抓包重放 - **客户子项目各自重造**:mjava-guangming 的 SSO 校验、mjava-shunfeng 的 dingtalk webhook 校验各自实现,代码不共享 需要在基座提供**可选启用**的"请求鉴权 + 防重放"统一能力。默认关闭(保护现有 mcli/shunfeng/guangming 生产服务不中断),子项目按需开启;mjava-com 未来的调用方签名也将复用本能力,避免重复建设。 与 `add-observability-foundation` 的 TraceId 互补:前者负责"日志可追溯",本 change 负责"调用不可伪造"。 ## What Changes 新增 3 个基座组件(全部放在 `mjava/`,子项目零代码改动即可通过配置启用): - `com.malk.filter.AuthFilter`:请求进入时校验 token/signature + 时间窗 + Nonce 去重;失败返回 `401/403` - `com.malk.utils.UtilSignature`:HMAC-SHA256 签名计算与验证工具类 - `com.malk.core.NonceCache`:基于 `UtilToken.TimedCache` 的 Nonce 去重缓存(封装 namespace + TTL = 时间窗) 配置开关: ```yaml mjava: auth: enabled: false # 默认关闭;子项目可按需打开 secret: ${AUTH_SECRET} # 服务端共享密钥(环境变量注入) window: 300 # 时间窗秒数,默认 5 分钟 nonce-cache-size: 10000 # Nonce 缓存条目上限(LRU 淘汰) exempt-paths: # 豁免路径清单(正则或 Ant 风格) - /actuator/** # 健康检查 - /api/*/callback/** # 第三方 webhook 回调(自带签名协议) ``` 另加 `@NoAuth` 注解,方法/类级别显式豁免。 ## Capabilities ### New Capabilities - `request-auth`:基于 HMAC-SHA256 + 共享密钥的统一请求鉴权 - `replay-guard`:基于时间窗 + Nonce 的防重放保护 ### Modified Capabilities ## Impact - **新增文件**:`AuthFilter.java` / `UtilSignature.java` / `NonceCache.java` / `AuthConfig.java` / `@NoAuth` 注解 / `AuthConfigProperties.java` - **不动**:`RequestFilter` / `RequestInterceptor` / `CatchException` 原职责 - **yml**:`application.yml` 新增 `mjava.auth.*` 结构,默认 `enabled: false` - **对 mcli / shunfeng / guangming**:零影响(`enabled: false` 默认不拦截) - **对 mjava-com**:未来的调用方鉴权直接用本 `UtilSignature` + `NonceCache`;mjava-com 的 `CallerAuthInterceptor` 设计可简化 ## Non-Goals - ❌ 不做 OAuth2 / OpenID Connect(重量级,不适合内部场景) - ❌ 不做 JWT 签发与刷新流程(当前是无状态 HMAC,够用;将来如需再单独提案) - ❌ 不做 mTLS(网络层配置由运维侧处理) - ❌ 不取代第三方 webhook 回调的供应商签名校验(钉钉 `DingCallbackCrypto` / 宜搭 token 验证等各自保留) - ❌ 不做角色/权限(RBAC/ABAC),只解决"是谁 + 请求是否合法 + 是否重放"三件事 - ❌ 本 change 不强制要求任何现存客户升级开启