2026-05-06-REQ-USR-003.md 2.3 KB

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

reviewer: superpower-code-reviewer

Review: REQ-USR-003 — round 2

结论

approve

Must-fix

(无)

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

  1. HIGH SQL 注入 — RESOLVED。UserQueryDTO 删除 column 字段;UserMapper.searchUsers 三参签名含 @Param("column") String column;UserMapper.xml 用 ${column};UserServiceImpl.search 用局部变量映射后通过 mapper 单独传入。
  2. HIGH spec § 6 deleted=true — RESOLVED。Service 实现 'true'/'false' → '1'/'0' 标准化(其它抛 PARAM_INVALID);XML deleted 分支用 CAST(#{queryValue} AS UNSIGNED) 兼容 bit(1);恢复 get_filterByDeletedTrue_returnsOnlyDeleted IT;新增 search_deletedQueryValueTrue_normalizedToOne 单测。
  3. MEDIUM XML deleted 边界 — RESOLVED。queryField=deleted 但 queryValue 空时仍保留默认过滤 u.bDeleted = 0,避免返回全量含已删除。

Nice-to-have

  • UserServiceImpl.search:212/214 — 直接 query.setQueryValue("1") 改写入参 DTO,单测靠副作用断言。语义上 service 不应突变 controller 入参;可改用局部 normalizedDeletedValue + @Param("deletedValue") 传给 mapper,XML 改用 #{deletedValue},更纯。
  • round 1 遗留的 6 条 IT 覆盖缺口(department equals / deleted=false / notContains / 排序 / matchType 非枚举 IT / 空结果 IT)+ UserMapperSearchIT 断言强化 + PageResult javadoc + QUERY_COLUMN_MAP 位置 + Base_Column_List 抽取——本轮也不在 must_fix 范畴,留待后续 sweep。

反例 / 测试覆盖缺口

Round 1 must_fix 1 + 2 + 3 三项均已落地:

  1. 注入:UserMapper.xml 唯一 ${...} 插值仅来自 service 白名单映射,外部输入完全经过 #{...} 参数化绑定。
  2. deleted 标准化:单测 search_deletedQueryValueTrue_normalizedToOne 钉死 query.getQueryValue() == "1";IT get_filterByDeletedTrue_returnsOnlyDeleted 端到端验证返回已删除用户。
  3. XML 边界:deleted 空值分支保留默认 u.bDeleted = 0,与 spec § 业务规则 1 一致。

mvn -B test 经 .env.local 注入后 144/144 全绿,无新高危。

核心结论:round 1 high 注入风险 + spec § 6 契约缺失全部修复;其余 nice-to-have 不阻塞,留下一 sweep。verdict: approve。