From ad0a9e1d98f26faf40ea554dd20b88b0f0f226a5 Mon Sep 17 00:00:00 2001 From: let5sne Date: Tue, 14 Jul 2026 16:31:14 +0800 Subject: [PATCH] fix(auth): disable fixed SMS codes in prod --- .../web/controller/CaptchaController.java | 7 ++--- .../CaptchaControllerSecurityTest.java | 27 +++++++++++++++++++ docs/BRD_IMPLEMENTATION_AUDIT.md | 2 ++ scripts/demo-check.sh | 2 ++ 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 backend/ruoyi-admin/src/test/java/org/dromara/web/controller/CaptchaControllerSecurityTest.java diff --git a/backend/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java b/backend/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java index 5990cd86..2b6f4ed2 100644 --- a/backend/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java +++ b/backend/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java @@ -62,14 +62,11 @@ public class CaptchaController { /** * 演示/开发兜底:配置后不真发短信,验证码固定为该值,把短信通道从演示关键路径摘掉。 - * prod profile 仅在 aihr.sms.demo-fixed-code-enabled=true 时临时放行。 + * prod profile 代码级禁用固定验证码,不接受配置开关绕过。 */ @Value("${aihr.sms.dev-fixed-code:}") private String smsDevFixedCode; - @Value("${aihr.sms.demo-fixed-code-enabled:false}") - private boolean smsDemoFixedCodeEnabled; - private final Environment environment; /** @@ -84,7 +81,7 @@ public class CaptchaController { @Pattern(regexp = RegexConstants.MOBILE, message = "{user.mobile.phone.number.not.valid}") String phonenumber) { String key = GlobalConstants.CAPTCHA_CODE_KEY + phonenumber; boolean fixedCodeEnabled = StringUtils.isNotBlank(smsDevFixedCode) - && (!environment.acceptsProfiles(Profiles.of("prod")) || smsDemoFixedCodeEnabled); + && !environment.acceptsProfiles(Profiles.of("prod")); if (fixedCodeEnabled) { log.warn("aihr.sms.dev-fixed-code 已启用,短信验证码走固定码,未真实发送短信"); RedisUtils.setCacheObject(key, smsDevFixedCode, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); diff --git a/backend/ruoyi-admin/src/test/java/org/dromara/web/controller/CaptchaControllerSecurityTest.java b/backend/ruoyi-admin/src/test/java/org/dromara/web/controller/CaptchaControllerSecurityTest.java new file mode 100644 index 00000000..e271a48e --- /dev/null +++ b/backend/ruoyi-admin/src/test/java/org/dromara/web/controller/CaptchaControllerSecurityTest.java @@ -0,0 +1,27 @@ +package org.dromara.web.controller; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; + +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@Tag("dev") +class CaptchaControllerSecurityTest { + + @Test + void fixedSmsCodeIsDisabledInProdWithoutOverride() throws Exception { + Path source = Path.of("src/main/java/org/dromara/web/controller/CaptchaController.java"); + if (!Files.exists(source)) { + source = Path.of("ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java"); + } + String code = Files.readString(source); + + assertTrue(code.contains("!environment.acceptsProfiles(Profiles.of(\"prod\"))")); + assertFalse(code.contains("smsDemoFixedCodeEnabled")); + assertFalse(code.contains("demo-fixed-code-enabled")); + } +} diff --git a/docs/BRD_IMPLEMENTATION_AUDIT.md b/docs/BRD_IMPLEMENTATION_AUDIT.md index b5a91790..ed3b38ad 100644 --- a/docs/BRD_IMPLEMENTATION_AUDIT.md +++ b/docs/BRD_IMPLEMENTATION_AUDIT.md @@ -2,6 +2,8 @@ 更新时间:2026-07-14 +- 2026-07-14 BRD G3/G6 生产验证码安全边界修复:`CaptchaController` 原先允许通过 `aihr.sms.demo-fixed-code-enabled=true` 在 `prod` profile 放行固定短信验证码,和项目要求的“生产代码级禁用”冲突;现仅允许非 `prod` profile 使用 `aihr.sms.dev-fixed-code`,删除生产覆盖开关,并新增源码契约回归与 `demo-check` marker。未修改线上配置或生产数据。 + ## 1. 审查口径 本记录以 [物业AI人力资源系统业务需求文档BRD.md](物业AI人力资源系统业务需求文档BRD.md) 为业务事实源,以 [FIGMA_IMPLEMENTATION_MATRIX.md](FIGMA_IMPLEMENTATION_MATRIX.md) 判断页面与视觉落地,以 [API_INTEGRATION.md](API_INTEGRATION.md) 和真实接口/浏览器结果判断运行闭环。 diff --git a/scripts/demo-check.sh b/scripts/demo-check.sh index 1b1325fd..949f99e2 100755 --- a/scripts/demo-check.sh +++ b/scripts/demo-check.sh @@ -611,6 +611,8 @@ contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/control contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "仅支持 txt/md/markdown/pdf/doc/docx/xls/xlsx/ppt/pptx/图片文件" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "/embeddings" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "aihr_knowledge_gap" +contains backend/ruoyi-admin/src/main/java/org/dromara/web/controller/CaptchaController.java '!environment.acceptsProfiles(Profiles.of("prod"))' +contains backend/ruoyi-admin/src/test/java/org/dromara/web/controller/CaptchaControllerSecurityTest.java "CaptchaControllerSecurityTest" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "requester_ext_party_id" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/controller/AihrSopController.java "currentRequesterExtPartyId" contains backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrSopSeedService.java "hasExplicitSopReviewDecision"