# 配置与接口说明

> 密码改造相关配置项与对外/对内接口约定。  
> 一期（互联网管理端短信双因子 + `ruoyi-crypto` 骨架）**后端已落地**，本文档与代码保持一致。

---

## 1. application.yml 配置

### 1.1 一期已实施配置示例

```yaml
# 密码改造总开关（一期：crypto 模块 Stub 已接入，二期起用于字段加解密）
crypto:
  enabled: true
  hsm:
    provider: stub                 # 开发联调 stub；生产改为 vendor-sdk 对接密码机
    hosts:
      - 127.0.0.1:8008
    connect-timeout-ms: 5000
    read-timeout-ms: 10000
    pool-size: 20
  keys:
    credential:
      hmac-index: 10
      sm4-index: 1
    personal:
      hmac-index: 11
      sm4-index: 2
    permission:
      hmac-index: 12
    log:
      hmac-index: 13
    business:
      hmac-index: 14
      sm4-index: 3

# 登录鉴别
# auth-mode: ruoyi     → 若依默认登录（账号+密码+图形验证码），不要求 smsCode
# auth-mode: sms-2fa  → 互联网双因子（还须 sys_login_policy 命中 SMS_2FA）
login:
  auth-mode: sms-2fa
  network-zone: INTERNET          # INTERNAL / INTERNET
  internet-sms:
    enabled: true                 # auth-mode 未配置时的等价开关；false = 若依默认登录
    code-length: 6
    code-ttl-seconds: 300
    send-interval-seconds: 60

# 短信网关（登录双因子）
sms:
  provider: aliyun
  aliyun:
    enabled: true
    dry-run: true                 # true=开发态仅写日志；生产配齐密钥后设 false
    access-key-id: ${ALIYUN_SMS_ACCESS_KEY_ID:}
    access-key-secret: ${ALIYUN_SMS_ACCESS_KEY_SECRET:}
    sign-name: ${ALIYUN_SMS_SIGN_NAME:}
    template-code: ${ALIYUN_SMS_TEMPLATE_CODE:}   # 模板变量须含 code
    region: cn-hangzhou
    request-timeout-seconds: 10
```

### 1.2 切换若依默认登录（单配置项）

任选其一即可恢复改造前登录方式（**无需** `smsCode`）：

| 方式 | 配置 | 说明 |
| --- | --- | --- |
| **推荐** | `login.auth-mode: ruoyi` | 语义清晰，优先于下方开关 |
| 等价 | `login.internet-sms.enabled: false` | 与 `auth-mode: ruoyi` 效果相同 |

修改后重启应用生效。`/login/sms/send` 在关闭双因子时将返回「短信双因子登录未启用」。

### 1.3 配置项说明

| 配置项 | 说明 |
| --- | --- |
| `crypto.enabled` | 密码改造总开关；false 时业务可跳过加解密（仅建议迁移双写期） |
| `crypto.hsm.provider` | `stub`=BouncyCastle 开发实现；生产对接密码机 SDK |
| `crypto.keys.*` | 各数据类型在密码机内的密钥索引（非密钥本身） |
| `login.auth-mode` | `ruoyi` / `sms-2fa`；非空时优先于子开关 |
| `login.network-zone` | 与 `sys_login_policy.network_zone` 配合解析策略 |
| `login.internet-sms.*` | OTP 长度、Redis TTL、同 IP 发送间隔 |
| `sms.aliyun.dry-run` | `true` 或未配齐 AccessKey 时仅打日志 Stub，不调阿里云 API |
| `sms.aliyun.*` | 阿里云 dysmsapi SendSms 参数 |

### 1.4 说明

> UKey 证书登录（`/login/cert*`、`sign-server.*`）本期已撤销，仅保留库表字段与策略枚举预留；详见技术方案 §2.2。完整性巡检、告警等见实施计划。

---

## 2. 身份鉴别接口

### 2.1 短信双因子（一期已实施）

| 方法 | 路径 | 说明 | 状态 |
| --- | --- | --- | --- |
| POST | `/login/sms/send` | 发送登录短信验证码 | ✅ 已实施 |
| POST | `/login` | 原接口增加可选字段 `smsCode` | ✅ 已实施 |

**前置条件**：`login.auth-mode=sms-2fa`（或 `internet-sms.enabled=true`），且 `sys_login_policy` / 用户 `login_policy` 解析为 `SMS_2FA`。

**POST /login/sms/send**

```json
{
  "username": "admin"
}
```

> sms-2fa 下不要求图形验证码；防刷依赖同 IP 发送间隔（`login.internet-sms.send-interval-seconds`）。

**POST /login（互联网双因子）**

```json
{
  "username": "admin",
  "password": "******",
  "smsCode": "123456"
}
```

**POST /login（若依默认，`auth-mode=ruoyi`）**

```json
{
  "username": "admin",
  "password": "******",
  "code": "图形验证码",
  "uuid": "图形验证码uuid"
}
```

**短信相关错误提示（i18n）**

| 场景 | 用户提示 |
| --- | --- |
| 缺少 smsCode | 请输入短信验证码 |
| 验证码错误 | 短信验证码错误 |
| 验证码过期 | 短信验证码已失效 |
| 发送过频 | 短信发送过于频繁，请稍后再试 |
| 未绑定手机 | 账号未绑定手机号，无法登录 |

### 2.2 证书登录（⏳ 待实施）

| 方法 | 路径 | 说明 | 状态 |
| --- | --- | --- | --- |
| GET | `/login/cert/challenge` | 获取登录随机数 challenge | ⏳ 待实施 |
| POST | `/login/cert` | 证书验签登录 | ⏳ 待实施 |

**已预留**：`sys_user.cert_sn` / `cert_subject`、`login_policy=CERT`、`LoginPolicyType.CERT`。本期不提供接口与验签服务器对接。

---

## 3. 内部实现（一期已落地代码）

### 3.1 模块与类路径

| 模块 | 包/类 | 说明 |
| --- | --- | --- |
| `ruoyi-crypto` | `com.ruoyi.crypto.service.CryptoService` | SM3/SM4 统一接口 |
| `ruoyi-crypto` | `StubCryptoServiceImpl` | 开发态密码机 Stub |
| `ruoyi-framework` | `LoginSmsService` | 短信双因子发送/校验 |
| `ruoyi-framework` | `LoginProperties` | `login.*` 配置 |
| `ruoyi-framework` | `AliyunSmsGatewayClient` | 阿里云 dysmsapi 封装 |
| `ruoyi-framework` | `SmsProperties` | `sms.*` 配置 |
| `ruoyi-system` | `SysLoginPolicyServiceImpl` | 登录策略解析 |
| `baqing-admin` | `SysLoginController` | `/login`、`/login/sms/send` |

### 3.2 CryptoService

```java
public interface CryptoService {
    String hmacSm3(byte[] plain, CryptoDataType dataType);
    String encryptSm4(String plainText, CryptoDataType dataType);
    String decryptSm4(String cipherText, CryptoDataType dataType);
    boolean verifyHmac(byte[] plain, String storedHmac, CryptoDataType dataType);
}
```

### 3.3 短信网关 SDK

| 项 | 值 |
| --- | --- |
| Maven 坐标 | `com.aliyun:alibabacloud-dysmsapi20170525:4.0.10` |
| 实现类 | `AliyunSmsGatewayClient` |
| 调用 API | `AsyncClient.sendSms` |
| 模板参数 | `{"code":"123456"}` |

**开发联调**：`sms.aliyun.dry-run=true` 时，验证码写入应用日志（关键字 `【短信Stub】`），无需真实发短信。

**生产启用**：配置 AccessKey、签名、模板，设 `dry-run=false`。

### 3.4 Redis 约定

| Key | 说明 |
| --- | --- |
| `login:sms:{mobile}` | OTP 明文，TTL 默认 300s，校验成功后删除 |
| `login:sms:limit:{ip}` | 同 IP 发送间隔，默认 60s |

### 3.5 IntegrityService（二期规划）

```java
public interface IntegrityService {
    String computeAndStore(String tableName, Object entity);
    void verifyOnRead(String tableName, Object entity);
    void patrolTable(String tableName, int batchSize);
}
```

### 3.6 异常与前端提示

| 异常 | HTTP | 用户提示 |
| --- | --- | --- |
| `SmsCodeRequiredException` | 200 + 业务错误 | 请输入短信验证码 |
| `SmsCodeException` | 200 + 业务错误 | 短信验证码错误 |
| `SmsCodeExpireException` | 200 + 业务错误 | 短信验证码已失效 |
| `CryptoIntegrityException` | 409 | 数据完整性校验失败（二期） |
| `CryptoException` | 500 | 系统安全服务暂不可用 |
| `CertVerifyException` | 401 | 证书验签失败 |

---

## 4. 数据库脚本

| 脚本 | 说明 | 状态 |
| --- | --- | --- |
| `sql/crypto_phase1.sql` | 一期：`sys_user` 扩展、`sys_login_policy` | ✅ 已提供 |
| `sql/crypto_migration.sql` | 二～三期全量 DDL | ⏳ 待编写 |

---

## 5. 联调检查清单

### 一期（互联网双因子）

- [x] `ruoyi-crypto` Stub SM3/SM4 单元测试
- [x] `POST /login/sms/send` + `POST /login` 后端接口
- [x] `login.auth-mode` 切换若依默认登录
- [x] 阿里云 SDK 集成（dry-run / 真实发送）
- [ ] 执行 `sql/crypto_phase1.sql`
- [ ] 管理员账号绑定手机号
- [x] 前端登录页接入 `smsCode`
- [ ] 等保测评环境 `auth-mode=sms-2fa` + `dry-run=false`

### 后续阶段

- [ ] 密码机 SM3/SM4 连通性（替换 Stub）
- [ ] UKey 证书登录端到端
- [ ] 篡改库中 HMAC 后读接口触发告警

---

## 6. 厂商信息登记（联调填写）

| 项 | 值 |
| --- | --- |
| 密码机厂商 | （待填） |
| 密码机型号 | （待填） |
| SDK 版本 | （待填） |
| 验签服务器厂商 | （待填） |
| 验签接口文档版本 | （待填） |
| 短信网关 | 阿里云 dysmsapi |
| 短信 SDK | `alibabacloud-dysmsapi20170525` 4.0.10 |
