4.6 KiB
修管理后台登录 2FA 设备验证失效 (P0 安全降级)
日期: 2026-05-06 类型: fix (P0 安全降级,后端配置默认值修复,无前端影响) PR: wx/HL #1699 (已合并 dev,等运维/用户合 main 部署正式) 关联工单: #1698 引入: 2026-04-03 PR #144 (commit 538635e)
问题
切换电脑/浏览器登录管理后台,应该触发企业微信扫码 2 次验证 (设备指纹+企微 2FA);实际任何账号(不只内置 admin)直接账号密码即可登录,2FA 完全失效。
影响 dev/test/prod 全环境近一个月。
根因
hl-user-service/src/main/resources/application.yml:69-70:
auth:
2fa:
enabled: false # ← 默认关
AdminAuthService.java:155 跳过判断:
if ("admin".equals(admin.getUsername()) || !twoFactorEnabled) {
// 直接发 token,跳过设备指纹比对+企微 2FA 流程
}
!twoFactorEnabled = !false = true → 任何账号都跳过。
Nacos dev/test/prod 三套 hl-user-service-{env}.yml 均未覆写 auth.2fa.enabled,全部吃 application.yml 默认值。
引入溯源
PR #144 (2026-04-03 commit 538635e) "代码安全审计修复(8项)":
CRITICAL: 2FA跳过改为显式配置(auth.2fa.enabled),移除环境名判断
意图把"用环境名判 dev 跳过"换成"用配置开关",默认值意外写反 —— 安全修复想让默认 ON,实际写成 OFF。
修复
| 文件 | 改动 |
|---|---|
hl-user-service/src/main/resources/application.yml |
enabled: false → true + 注释说明 |
nacos-config/hl-user-service-dev.yml |
显式覆写 auth.2fa.enabled: true 防回归 |
hl-user-service/.../config/Auth2faDefaultEnabledAuditTest.java |
新增守护单测,防 PR #144 类反转再发 |
内置 admin 账号在 line 155 第一条件 "admin".equals(username) 不变,仍跳过 2FA 避免 super-admin 锁死。
影响范围
- 受波及账号: 所有非内置 admin 的管理员 (即所有真实业务账号)
- 数据污染: 无 (仅认证流程降级,未污染数据)
- 回滚:
git revert1 commit
验证
单测
mvn test -Dtest=AdminAuthServiceTest→ 58/58 全绿 (含已有的login_untrustedDevice_requires2FA/login_trustedDevice_issuesToken/login_superAdmin_skips2FA_issuesTokenDirectly)mvn test -Dtest=Auth2faDefaultEnabledAuditTest→ 1/1 (反向验证: 改回 false 立即报expected: <true> but was: <false>)
测试服 round-trip (dev 部署后)
# 期望 1: 非 admin 账号新设备登录 → requireTwoFa=true && token=null
curl -k -X POST 'https://api.test.1814.love:9443/admin/auth/login' \
-H 'Content-Type: application/json' \
-H 'X-Device-Fingerprint: NEW_DEVICE_TEST' \
-d '{"username":"<非admin账号>","password":"<密码>"}'
# 期望: {"code":"200","data":{"requireTwoFa":true,"token":null,...}}
# 期望 2: 内置 admin 仍跳过 2FA
curl -k -X POST 'https://api.test.1814.love:9443/admin/auth/login' \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"Admin@123456"}'
# 期望: {"code":"200","data":{"token":"eyJ...",...}} (token 直接发)
# 期望 3: 已信任设备直发 token (admin_device.is_trusted=true)
# 期望 4: 换浏览器 (不同 fingerprint) → admin_device 不命中 → requireTwoFa=true
部署计划
- ✅ dev 测试服: 自动部署 (PR 合并触发)
- ⏳ prod: 用户手动合 dev → main 后,运维/管理员通过 Deploy Panel 触发 hl-user-service prod 部署。仅 application.yml 改动,nacos prod 无需推送(prod nacos 未覆写,jar 内默认值 true 立即生效)。
- 如需 prod nacos 也加显式覆写防回归,在
正式环境Nacos配置/hl-user-service-prod.yml已落本地参考,运维同步推 nacos prod 即可。
经验沉淀
落 memory/experience/backend-dev/yml-default-value-must-be-secure-by-default.md —
配置默认值反转规则: 任何"启用/禁用"类配置 (enabled/required/strict/validate),默认值必须取安全/严格那一侧:
auth.2fa.enabled默认true(开启)validate-on-migrate默认true(校验)strict-mode默认true(严格)cors.allow-all-origins默认false(拒绝)
把不安全/松散值留给 nacos 显式覆写,绝不让 application.yml 默认值成为安全降级源。
防回归手段: 给关键 enabled: true 配置写 *DefaultEnabledAuditTest 守护测试,任何回退立即编译期/单测期阻断。
通知
- 后端独立修复,无前端改动需求 (mmg/yst 不用动)
- 用户/运维: 部署 prod 后请告知,以便 round-trip 4 个验证场景闭环 + 关闭工单 #1698