2026-05-06-REQ-USR-004.md 2.82 KB

req_id: REQ-USR-004 date: 2026-05-06 round: 2

reviewer: superpower-code-reviewer

Review: REQ-USR-004 — round 2

结论

approve

Must-fix

(无)

Round 1 三条 must_fix 处理结果(commit d439c0d9):

  1. CRITICAL JwtTokenProviderTest 硬编码生产 JWT_SECRET — RESOLVED。test SECRET 改为 fake 32-byte hex(line 21);.env.local JWT_SECRET 已旋转为新随机值。遗留运维项:旧值已入 commit b7ed804a git history,所有已部署环境必须同步轮换 JWT_SECRET。
  2. HIGH InMemoryLoginAttemptStore 锁定到期不重置 — RESOLVED。cooldownSeconds 过期路径 store.remove,recordFailure compute 入口检测 prev.lockUntil 过期重建 FailRecord;spec § 业务规则 4 第 4 条达成。
  3. MEDIUM 验收 #9 无测试 — RESOLVED。补 cooldown_afterExpiry_resetsCount 单测(含 reset 后再 4 次未锁、第 5 次再锁的完整往返)+ login_afterLockExpiry_returns200 IT;expireLockForTest 改 public 解决跨包可见性。

Nice-to-have

  • backend/src/main/java/com/xly/erp/module/usr/controller/LoginController.java + service — spec § 业务规则 7 客户端 IP 审计未实施;service 未拿 HttpServletRequest.getRemoteAddr()需在模块完成报告 § ⑩ 登记技术债
  • backend/src/test/java/com/xly/erp/module/usr/service/LoginServiceImplTest.java — login_successUpdatesTLastLoginDate_viaSetClause 仍只 verify(...).update(isNull(), any(Wrapper.class)),没断言 LambdaUpdateWrapper 的 set 子句包含 tLastLoginDate(plan Step 4.1 要求)。
  • backend/src/main/java/com/xly/erp/config/SecurityConfig.java — plan Step 5.2 要求 requestMatchers("/api/auth/login").permitAll() 显式白名单;当前 anyRequest().permitAll() 等价覆盖但未做 plan 偏离登记。
  • backend/src/main/java/com/xly/erp/common/exception/GlobalExceptionHandler.java:17 — java.util.Map fully-qualified;下次 sweep 加 import。
  • backend/src/main/java/com/xly/erp/module/usr/security/InMemoryLoginAttemptStore.java:51 — expireLockForTest 已 public 但住在生产包;下一 sweep 可挪到 src/test 的 testutil 包。

反例 / 测试覆盖缺口

Round 1 三项 must_fix 全部解决:

  1. JwtTokenProviderTest SECRET 改 fake + .env.local 已旋转;运维侧需轮换部署环境。
  2. cooldownSeconds + recordFailure 双路径处理过期重置;business rule #4 完整。
  3. 验收 #9 单测 + IT 双层覆盖;reset 后能重新触发新一轮锁定。

mvn -B test 经 .env.local 注入后 172/172 全绿;scripts/test.sh GREEN;无新高危。

核心结论:critical + high + medium 三项关键修复已落地。剩余 5 条 nice-to-have(IP 审计 / SET 子句捕获 / SecurityConfig 显式白名单 / Map import / testutil 移植)在模块完成报告 § ⑩ 登记后留给后续 sweep。verdict: approve。