wwh 1 день назад
Родитель
Сommit
ebe8c48a6a

+ 3 - 3
baqing-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java

@@ -64,7 +64,7 @@ public class SysLoginController
64 64
     /**
65 65
      * 管理端登录。
66 66
      * <p>
67
-     * 互联网部署且策略为 SMS_2FA 时,除 username/password/图形验证码外还须传 {@code smsCode}
67
+     * 互联网部署且策略为 SMS_2FA 时,须传 username/password/{@code smsCode}(不要求图形验证码)
68 68
      * 须先调用 {@link #sendLoginSms} 获取短信验证码。
69 69
      * </p>
70 70
      * 
@@ -85,11 +85,11 @@ public class SysLoginController
85 85
     /**
86 86
      * 发送登录短信验证码(互联网双因子第一步)。
87 87
      * <p>
88
-     * 请求体与登录类似,须携带图形验证码 uuid/code 防刷。
88
+     * 请求体仅需 username;sms-2fa 下不校验图形验证码,依赖 IP 发送间隔防刷。
89 89
      * 用户须已绑定手机号;验证码写入 Redis,开发环境可在日志中查看 Stub 短信内容。
90 90
      * </p>
91 91
      *
92
-     * @param body username + 图形验证码
92
+     * @param body username
93 93
      */
94 94
     @PostMapping("/login/sms/send")
95 95
     public AjaxResult sendLoginSms(@RequestBody LoginSmsSendBody body)

+ 0 - 3
baqing-admin/src/test/java/com/ruoyi/framework/web/service/LoginSmsServiceTest.java

@@ -55,9 +55,6 @@ class LoginSmsServiceTest
55 55
     @Mock
56 56
     private SmsGatewayClient smsGatewayClient;
57 57
 
58
-    @Mock
59
-    private SysLoginService loginService;
60
-
61 58
     @Mock
62 59
     private LoginInforRecorder loginInforRecorder;
63 60
 

+ 3 - 3
doc/密码改造/README.md

@@ -26,8 +26,8 @@
26 26
 | `ruoyi-crypto` 模块 | ✅ Stub | `CryptoService` + BouncyCastle 开发实现 |
27 27
 | 阿里云短信 SDK | ✅ | `alibabacloud-dysmsapi20170525`,支持 `dry-run` 日志 Stub |
28 28
 | `sys_login_policy` | ✅ 代码+DDL | 脚本 `sql/crypto_phase1.sql` |
29
-| UKey 证书登录 | ⏳ 待实施 | 接口与验签服务器对接待二期 |
30
-| 前端登录改造 | ⏳ 待实施 | 可不改前端,用 API 联调后端 |
29
+| UKey 证书登录 | ⏳ 待实施 | 字段/策略枚举已预留(`cert_sn`、`LoginPolicyType.CERT`);接口未实现 |
30
+| 前端登录改造 | ✅ 短信双因子 | 支持 `VUE_APP_LOGIN_AUTH_MODE=ruoyi|sms-2fa` |
31 31
 | 字段 SM3/SM4 | ⏳ 二期 | MyBatis 拦截器、存量迁移 |
32 32
 
33 33
 ---
@@ -63,7 +63,7 @@ login:
63 63
 
64 64
 ## 外部依赖
65 65
 
66
-- **签名验签服务器**:国密 UKey 证书登录、SM2 验签(待联调
66
+- **签名验签服务器**:国密 UKey 证书登录、SM2 验签(待实施
67 67
 - **密码机(HSM)**:SM3-HMAC、SM4 加解密(一期 Stub,生产待对接)
68 68
 - **短信网关**:阿里云 dysmsapi(一期已集成 SDK)
69 69
 

+ 4 - 4
doc/密码改造/实施计划与验收.md

@@ -17,7 +17,7 @@
17 17
 
18 18
 ## 2. 一期:身份鉴别与密码框架
19 19
 
20
-> **进度说明(互联网管理端)**:后端短信双因子、`ruoyi-crypto` Stub、阿里云短信 SDK、`login.auth-mode` 切换已落地;UKey 证书登录与前端改造仍待实施
20
+> **进度说明**:后端短信双因子、`ruoyi-crypto` Stub、阿里云短信 SDK、`login.auth-mode` 切换已落地;UKey 证书登录接口已撤销,仅保留字段与策略枚举预留
21 21
 
22 22
 ### 2.1 任务清单
23 23
 
@@ -25,14 +25,14 @@
25 25
 | --- | --- | --- | --- |
26 26
 | 1.1 | 采购/部署密码机、验签服务器联调环境 | 联调报告 | ⏳ |
27 27
 | 1.2 | 新建 `ruoyi-crypto` 模块,`CryptoService` 封装 SM3/SM4 | 代码 + 单元测试(Stub) | ✅ |
28
-| 1.3 | 对接签名验签服务器,`/login/cert` 接口 | 证书登录可用 | ⏳ |
28
+| 1.3 | 对接签名验签服务器,`/login/cert` 接口 | 证书登录可用 | ⏳ 待实施 |
29 29
 | 1.4 | 短信双因子登录(互联网) | `/login/sms/send`、登录校验 | ✅ 后端 |
30 30
 | 1.4a | 阿里云短信 SDK 集成 | `AliyunSmsGatewayClient` + `dry-run` | ✅ |
31 31
 | 1.4b | 若依默认登录一键切换 | `login.auth-mode: ruoyi` | ✅ |
32
-| 1.5 | `sys_user` 增加 `cert_sn`、`login_policy` 等字段 | `sql/crypto_phase1.sql` | ✅ 脚本已提供 |
32
+| 1.5 | `sys_user` 增加 `cert_sn`、`login_policy` 等字段 | `sql/crypto_phase1.sql` | ✅ 脚本已提供(字段预留) |
33 33
 | 1.6 | `sys_login_policy` 配置与文档 | 策略可配置 | ✅ |
34 34
 | 1.7 | 安全审计:短信失败记 `sys_logininfor` | 日志可查 | ✅ |
35
-| 1.8 | 前端:登录页短信双因子、`api/login.js` | 待前端改造(后端可先 API 联调) |
35
+| 1.8 | 前端:登录页短信双因子、`api/login.js` |  |
36 36
 
37 37
 ### 2.2 验收标准
38 38
 

+ 10 - 8
doc/密码改造/应用密码改造技术方案.md

@@ -84,7 +84,9 @@ flowchart TB
84 84
 | 业务操作员 | 按角色配置 | 口令 + 可选短信/UKey | 由 `sys_login_policy` 配置 |
85 85
 | 移动端/App | 普通用户 | 现有口令/Token 体系 | 敏感接口可增加短信二次确认 |
86 86
 
87
-### 2.2 管理员 UKey 证书登录流程
87
+### 2.2 管理员 UKey 证书登录流程(⏳ 待实施)
88
+
89
+> 以下为设计方案;本期已撤销接口实现,仅保留 `sys_user.cert_sn` 等字段与 `LoginPolicyType.CERT` 枚举。
88 90
 
89 91
 ```mermaid
90 92
 sequenceDiagram
@@ -107,14 +109,14 @@ sequenceDiagram
107 109
     API->>API: 写 sys_logininfor + 安全审计
108 110
 ```
109 111
 
110
-**后端改造点**
112
+**后端改造点(待实施)**
111 113
 
112 114
 | 模块 | 改造内容 |
113 115
 | --- | --- |
114 116
 | `SysLoginController` | 新增 `GET /login/cert/challenge`、`POST /login/cert` |
115
-| `sys_user` | 增加 `cert_sn`、`cert_subject`、`login_policy` |
117
+| `sys_user` | 增加 `cert_sn`、`cert_subject`、`login_policy`(**字段已预留**) |
116 118
 | `TokenService` | 证书登录成功后与普通登录共用 JWT 签发逻辑 |
117
-| `SysLoginService` | 增加 `loginByCert`、`verifyCertSignature` |
119
+| 登录服务 | 增加证书验签登录与验签服务器对接 |
118 120
 | 权限 | 超级管理员角色可配置强制证书登录 |
119 121
 
120 122
 **验签失败处理**
@@ -126,8 +128,8 @@ sequenceDiagram
126 128
 
127 129
 **流程**
128 130
 
129
-1. `POST /login/sms/send`:校验图形验证码 → 发送短信 OTP 至 `sys_user.phonenumber`
130
-2. `POST /login`:提交 `username`、`password`、`smsCode`(图形验证码)
131
+1. `POST /login/sms/send`:提交账号 → 发送短信 OTP 至 `sys_user.phonenumber`(不校验图形验证码)
132
+2. `POST /login`:提交 `username`、`password`、`smsCode`(不要求图形验证码)
131 133
 3. 校验短信 OTP(Redis)→ 校验口令(BCrypt)→ 签发 Token,写登录日志
132 134
 
133 135
 **改造点(一期已实施)**
@@ -344,8 +346,8 @@ payload = dataType + "|" + keyVer + "|" + field1 + "|" + field2 + "|" ...
344 346
 
345 347
 | 期次 | 内容 | 状态 |
346 348
 | --- | --- | --- |
347
-| 一期 | 短信双因子后端、`ruoyi-crypto` Stub、阿里云短信 SDK、`auth-mode` 切换 | ✅ 后端已完成 |
348
-| 一期余 | UKey 证书登录、前端登录页 | ⏳ |
349
+| 一期 | 短信双因子后端、`ruoyi-crypto` Stub、阿里云短信 SDK、`auth-mode` 切换、前端短信双因子 | ✅ |
350
+| 一期余 | UKey 证书登录 | ⏳ 待实施(字段/策略枚举已预留) |
349 351
 | 二期 | `sys_user` / 权限表 / 日志表 SM3;个人信息 SM4 | ⏳ |
350 352
 | 三期 | 业务表按映射表改造;存量迁移 | ⏳ |
351 353
 | 四期 | 定时巡检、告警中心、密钥轮换 | ⏳ |

+ 10 - 41
doc/密码改造/配置与接口说明.md

@@ -79,36 +79,15 @@ sms:
79 79
 | `crypto.enabled` | 密码改造总开关;false 时业务可跳过加解密(仅建议迁移双写期) |
80 80
 | `crypto.hsm.provider` | `stub`=BouncyCastle 开发实现;生产对接密码机 SDK |
81 81
 | `crypto.keys.*` | 各数据类型在密码机内的密钥索引(非密钥本身) |
82
-| `login.auth-mode` | `ruoyi` / `sms-2fa`;非空时优先于 `internet-sms.enabled` |
82
+| `login.auth-mode` | `ruoyi` / `sms-2fa`;非空时优先于子开关 |
83 83
 | `login.network-zone` | 与 `sys_login_policy.network_zone` 配合解析策略 |
84 84
 | `login.internet-sms.*` | OTP 长度、Redis TTL、同 IP 发送间隔 |
85 85
 | `sms.aliyun.dry-run` | `true` 或未配齐 AccessKey 时仅打日志 Stub,不调阿里云 API |
86 86
 | `sms.aliyun.*` | 阿里云 dysmsapi SendSms 参数 |
87 87
 
88
-### 1.4 二期及以后配置(草案,尚未实施)
88
+### 1.4 说明
89 89
 
90
-```yaml
91
-crypto:
92
-  integrity:
93
-    verify-on-read: true
94
-    verify-before-update: true
95
-    patrol-cron: "0 0 2 * * ?"
96
-    patrol-batch-size: 500
97
-  alert:
98
-    sms-enabled: false
99
-    notify-roles: admin,security
100
-
101
-sign-server:
102
-  enabled: true
103
-  base-url: https://10.0.0.20:8443/sign-api
104
-  app-id: baqing-admin
105
-  connect-timeout-ms: 5000
106
-
107
-login:
108
-  cert:
109
-    enabled: true
110
-    challenge-ttl-seconds: 300
111
-```
90
+> UKey 证书登录(`/login/cert*`、`sign-server.*`)本期已撤销,仅保留库表字段与策略枚举预留;详见技术方案 §2.2。完整性巡检、告警等见实施计划。
112 91
 
113 92
 ---
114 93
 
@@ -127,20 +106,18 @@ login:
127 106
 
128 107
 ```json
129 108
 {
130
-  "username": "admin",
131
-  "uuid": "图形验证码uuid",
132
-  "code": "图形验证码"
109
+  "username": "admin"
133 110
 }
134 111
 ```
135 112
 
113
+> sms-2fa 下不要求图形验证码;防刷依赖同 IP 发送间隔(`login.internet-sms.send-interval-seconds`)。
114
+
136 115
 **POST /login(互联网双因子)**
137 116
 
138 117
 ```json
139 118
 {
140 119
   "username": "admin",
141 120
   "password": "******",
142
-  "code": "图形验证码",
143
-  "uuid": "图形验证码uuid",
144 121
   "smsCode": "123456"
145 122
 }
146 123
 ```
@@ -166,22 +143,14 @@ login:
166 143
 | 发送过频 | 短信发送过于频繁,请稍后再试 |
167 144
 | 未绑定手机 | 账号未绑定手机号,无法登录 |
168 145
 
169
-### 2.2 证书登录(一期预留,未实施)
146
+### 2.2 证书登录(⏳ 待实施)
170 147
 
171 148
 | 方法 | 路径 | 说明 | 状态 |
172 149
 | --- | --- | --- | --- |
173 150
 | GET | `/login/cert/challenge` | 获取登录随机数 challenge | ⏳ 待实施 |
174 151
 | POST | `/login/cert` | 证书验签登录 | ⏳ 待实施 |
175 152
 
176
-**POST /login/cert 请求体(规划)**
177
-
178
-```json
179
-{
180
-  "certBase64": "MIIC...",
181
-  "signedData": "MEUCI...",
182
-  "challenge": "a1b2c3d4-e5f6-..."
183
-}
184
-```
153
+**已预留**:`sys_user.cert_sn` / `cert_subject`、`login_policy=CERT`、`LoginPolicyType.CERT`。本期不提供接口与验签服务器对接。
185 154
 
186 155
 ---
187 156
 
@@ -250,7 +219,7 @@ public interface IntegrityService {
250 219
 | `SmsCodeExpireException` | 200 + 业务错误 | 短信验证码已失效 |
251 220
 | `CryptoIntegrityException` | 409 | 数据完整性校验失败(二期) |
252 221
 | `CryptoException` | 500 | 系统安全服务暂不可用 |
253
-| `CertVerifyException` | 401 | 证书验签失败(待实施) |
222
+| `CertVerifyException` | 401 | 证书验签失败 |
254 223
 
255 224
 ---
256 225
 
@@ -273,7 +242,7 @@ public interface IntegrityService {
273 242
 - [x] 阿里云 SDK 集成(dry-run / 真实发送)
274 243
 - [ ] 执行 `sql/crypto_phase1.sql`
275 244
 - [ ] 管理员账号绑定手机号
276
-- [ ] 前端登录页接入 `smsCode`(见前端方案,可选)
245
+- [x] 前端登录页接入 `smsCode`
277 246
 - [ ] 等保测评环境 `auth-mode=sms-2fa` + `dry-run=false`
278 247
 
279 248
 ### 后续阶段

+ 3 - 3
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginSmsSendBody.java

@@ -3,7 +3,7 @@ package com.ruoyi.common.core.domain.model;
3 3
 /**
4 4
  * 登录短信验证码发送请求体({@code POST /login/sms/send})。
5 5
  * <p>
6
- * 字段与 {@link LoginBody} 中图形验证码部分一致,用于在发送短信前完成人机校验,防止接口被恶意刷短信
6
+ * sms-2fa 模式下仅需 {@link #username};{@link #code}/{@link #uuid} 为兼容保留字段,后端不再校验
7 7
  * 不包含密码与 smsCode。
8 8
  * </p>
9 9
  */
@@ -12,10 +12,10 @@ public class LoginSmsSendBody
12 12
     /** 待登录的系统账号(sys_user.user_name) */
13 13
     private String username;
14 14
 
15
-    /** 用户输入的图形验证码 */
15
+    /** 兼容保留:图形验证码(sms-2fa 下不使用) */
16 16
     private String code;
17 17
 
18
-    /** 获取图形验证码时接口返回的 uuid,与 Redis 中 captcha_codes:{uuid} 对应 */
18
+    /** 兼容保留:图形验证码 uuid(sms-2fa 下不使用) */
19 19
     private String uuid;
20 20
 
21 21
     public String getUsername()

+ 8 - 15
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/LoginSmsService.java

@@ -6,7 +6,6 @@ import java.util.List;
6 6
 import java.util.concurrent.TimeUnit;
7 7
 import java.util.stream.Collectors;
8 8
 import org.springframework.beans.factory.annotation.Autowired;
9
-import org.springframework.context.annotation.Lazy;
10 9
 import org.springframework.stereotype.Service;
11 10
 import com.ruoyi.common.constant.CacheConstants;
12 11
 import com.ruoyi.common.constant.Constants;
@@ -73,11 +72,6 @@ public class LoginSmsService
73 72
     @Autowired
74 73
     private SmsGatewayClient smsGatewayClient;
75 74
 
76
-    /** 复用图形验证码校验逻辑,与 {@link SysLoginService#validateCaptcha} 保持一致 */
77
-    @Autowired
78
-    @Lazy
79
-    private SysLoginService loginService;
80
-
81 75
     /** 异步写 sys_logininfor,与 Spring 容器解耦便于单测 */
82 76
     @Autowired
83 77
     private LoginInforRecorder loginInforRecorder;
@@ -85,20 +79,19 @@ public class LoginSmsService
85 79
     /**
86 80
      * 发送登录短信验证码。
87 81
      * <p>
88
-     * 流程:图形验证码 → 开关/策略校验 → 用户与手机号校验 → IP 频控 → 生成 OTP 写 Redis → 调短信网关。
82
+     * 流程:开关/策略校验 → 用户与手机号校验 → IP 频控 → 生成 OTP 写 Redis → 调短信网关。
83
+     * sms-2fa 模式下不校验图形验证码,依赖 IP 发送间隔防刷。
89 84
      * 安全注意:用户不存在时仍返回统一错误文案({@link UserNotExistsException}),避免枚举用户名。
90 85
      * </p>
91 86
      *
92
-     * @param body 含 username、图形验证码 uuid/code
87
+     * @param body 含 username(code/uuid 可省略)
93 88
      */
94 89
     public void sendLoginSms(LoginSmsSendBody body)
95 90
     {
96 91
         String username = StringUtils.trim(body.getUsername());
97
-        // 1. 图形验证码(与 /login 相同规则,防止接口被刷)
98
-        loginService.validateCaptcha(username, body.getCode(), body.getUuid());
99 92
         assertInternetSmsEnabled();
100 93
 
101
-        // 2. 用户必须存在且当前策略要求短信双因子
94
+        // 1. 用户必须存在且当前策略要求短信双因子
102 95
         SysUser user = userService.selectUserByUserName(username);
103 96
         if (user == null)
104 97
         {
@@ -110,7 +103,7 @@ public class LoginSmsService
110 103
             throw new ServiceException("当前账号无需短信验证码登录");
111 104
         }
112 105
 
113
-        // 3. 手机号来自 sys_user.phonenumber(二期可改为 SM4 解密后比对)
106
+        // 2. 手机号来自 sys_user.phonenumber(二期可改为 SM4 解密后比对)
114 107
         String mobile = resolveMobile(user);
115 108
         if (StringUtils.isEmpty(mobile))
116 109
         {
@@ -118,7 +111,7 @@ public class LoginSmsService
118 111
             throw new UserMobileNotBoundException();
119 112
         }
120 113
 
121
-        // 4. 同 IP 发送间隔限制(默认 60s,配置 login.internet-sms.send-interval-seconds)
114
+        // 3. 同 IP 发送间隔限制(默认 60s,配置 login.internet-sms.send-interval-seconds)
122 115
         String clientIp = IpUtils.getIpAddr();
123 116
         String limitKey = CacheConstants.LOGIN_SMS_LIMIT_KEY + clientIp;
124 117
         if (redisCache.hasKey(limitKey))
@@ -127,14 +120,14 @@ public class LoginSmsService
127 120
             throw new SmsSendIntervalException();
128 121
         }
129 122
 
130
-        // 5. 生成数字 OTP 并写入 Redis(按手机号维度,非用户名,避免换账号刷同一手机)
123
+        // 4. 生成数字 OTP 并写入 Redis(按手机号维度,非用户名,避免换账号刷同一手机)
131 124
         String code = generateCode(loginProperties.getInternetSms().getCodeLength());
132 125
         String smsKey = CacheConstants.LOGIN_SMS_CODE_KEY + mobile;
133 126
         int ttl = loginProperties.getInternetSms().getCodeTtlSeconds();
134 127
         redisCache.setCacheObject(smsKey, code, ttl, TimeUnit.SECONDS);
135 128
         redisCache.setCacheObject(limitKey, "1", loginProperties.getInternetSms().getSendIntervalSeconds(), TimeUnit.SECONDS);
136 129
 
137
-        // 6. 调用短信网关;失败则回滚 Redis 中的 OTP
130
+        // 5. 调用短信网关;失败则回滚 Redis 中的 OTP
138 131
         boolean sent = smsGatewayClient.sendLoginCode(mobile, code);
139 132
         if (!sent)
140 133
         {

+ 14 - 8
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java

@@ -2,7 +2,6 @@ package com.ruoyi.framework.web.service;
2 2
 
3 3
 import javax.annotation.Resource;
4 4
 import org.springframework.beans.factory.annotation.Autowired;
5
-import org.springframework.context.annotation.Lazy;
6 5
 import org.springframework.security.authentication.AuthenticationManager;
7 6
 import org.springframework.security.authentication.BadCredentialsException;
8 7
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -24,6 +23,7 @@ import com.ruoyi.common.utils.DateUtils;
24 23
 import com.ruoyi.common.utils.MessageUtils;
25 24
 import com.ruoyi.common.utils.StringUtils;
26 25
 import com.ruoyi.common.utils.ip.IpUtils;
26
+import com.ruoyi.framework.config.properties.LoginProperties;
27 27
 import com.ruoyi.framework.manager.AsyncManager;
28 28
 import com.ruoyi.framework.manager.factory.AsyncFactory;
29 29
 import com.ruoyi.framework.security.context.AuthenticationContextHolder;
@@ -35,6 +35,7 @@ import com.ruoyi.system.service.ISysUserService;
35 35
  * <p>
36 36
  * 若依默认口令登录流程;密码改造一期在互联网管理端增加短信双因子:
37 37
  * 当 {@link LoginSmsService#requiresSmsTwoFactor} 为 true 时,须在口令认证前校验 {@code smsCode}。
38
+ * {@code login.auth-mode=sms-2fa} 时以短信 OTP 代替图形验证码,不再校验图片验证码。
38 39
  * </p>
39 40
  * 
40 41
  * @author ruoyi
@@ -57,9 +58,10 @@ public class SysLoginService
57 58
     @Autowired
58 59
     private ISysConfigService configService;
59 60
 
60
-    /** 互联网短信双因子;与 LoginSmsService 存在循环依赖,使用 @Lazy 打破 */
61 61
     @Autowired
62
-    @Lazy
62
+    private LoginProperties loginProperties;
63
+
64
+    @Autowired
63 65
     private LoginSmsService loginSmsService;
64 66
 
65 67
     /**
@@ -79,7 +81,8 @@ public class SysLoginService
79 81
     /**
80 82
      * 登录验证(支持互联网短信双因子)。
81 83
      * <p>
82
-     * 完整顺序:图形验证码 → 用户名/密码格式与黑名单 → <b>短信 OTP(若策略要求)</b> → Spring Security 口令认证 → 签发 Token。
84
+     * 完整顺序:图形验证码(非 sms-2fa)→ 用户名/密码格式与黑名单 → <b>短信 OTP(若策略要求)</b>
85
+     * → Spring Security 口令认证 → 签发 Token。
83 86
      * {@code smsCode} 对非双因子用户可省略;双因子用户缺失或错误将在口令校验前被拒绝并记登录失败审计。
84 87
      * </p>
85 88
      *
@@ -87,8 +90,11 @@ public class SysLoginService
87 90
      */
88 91
     public String login(String username, String password, String code, String uuid, String smsCode)
89 92
     {
90
-        // 验证码校验
91
-        validateCaptcha(username, code, uuid);
93
+        // sms-2fa 以短信 OTP 代替图形验证码
94
+        if (!loginProperties.isSmsTwoFactorActive())
95
+        {
96
+            validateCaptcha(username, code, uuid);
97
+        }
92 98
         // 登录前置校验
93 99
         loginPreCheck(username, password);
94 100
 
@@ -135,8 +141,8 @@ public class SysLoginService
135 141
     /**
136 142
      * 校验图形验证码。
137 143
      * <p>
138
-     * 登录与 {@code POST /login/sms/send} 共用此方法;验证码一次性使用(校验后删 Redis)。
139
-     * 设为 public 供 {@link LoginSmsService} 复用
144
+     * 登录与短信发送共用此方法;验证码一次性使用(校验后删 Redis)。
145
+     * sms-2fa 登录流程不再调用本方法
140 146
      * </p>
141 147
      * 
142 148
      * @param username 用户名(仅用于记登录失败日志)

+ 4 - 0
sql/crypto_phase1.sql

@@ -38,3 +38,7 @@ VALUES ('admin', 'INTERNET', 'SMS_2FA', '1', '互联网超级管理员双因子'
38 38
 -- 互联网环境:默认策略(未匹配角色时)
39 39
 INSERT INTO sys_login_policy (role_key, network_zone, policy_type, enabled, remark, create_time)
40 40
 VALUES (NULL, 'INTERNET', 'SMS_2FA', '1', '互联网管理端默认双因子', NOW());
41
+
42
+-- 内网/专网:默认口令登录(CERT 策略枚举与 cert_sn 字段一期仅预留,证书登录接口待实施)
43
+INSERT INTO sys_login_policy (role_key, network_zone, policy_type, enabled, remark, create_time)
44
+VALUES (NULL, 'INTERNAL', 'PASSWORD', '1', '内网管理端默认口令登录', NOW());