# 认证与登录设计

---
DDS-Section: 3. 认证与登录设计
DDS-Lines: L174-L201
---

## 登录流程（RSA + JWT）

```
1. 前端调用 GET /api/auth/rsa/public-key 获取公钥（30天有效）
2. 前端用 RSA-OAEP(SHA-256, 2048) 加密密码
3. 前端提交 POST /api/auth/login (encrypted_password)
4. 后端 RSAService 解密
5. 后端 AuthService 用 bcrypt 校验 password_hash
6. 生成 HS256 JWT (4h 有效期)
7. 返回 Token + UserDTO + 附加标识
```

## 登录响应附加标识

| 字段 | 类型 | 说明 |
|:---|:---|:---|
| `must_change_password` | bool | 首次登录或密码重置后需强制改密 |
| `password_expire_days` | int | 密码剩余有效天数（7天内提示） |
| `account_expire_days` | int | 账户剩余有效天数（7天内提示） |

## 密钥与密码策略

| 配置项 | 值 | 说明 |
|:---|:---|:---|
| RSA 算法 | RSA-OAEP(SHA-256) | 2048 位密钥 |
| RSA 有效期 | 30 天 | 过期自动生成新密钥对 |
| 密码存储 | bcrypt | 默认成本因子 |
| 密码有效期 | 90 天 | 到期需修改密码 |
| JWT 算法 | HS256 | - |
| JWT 有效期 | 4 小时 | 无刷新机制 |

## JWT 中间件行为

| 步骤 | 动作 |
|:---|:---|
| 1 | 解析 `Authorization: Bearer <token>` |
| 2 | 校验签名与过期时间 |
| 3 | 校验 `claims.Status == "active"` |
| 4 | 校验 `account_expires_at` 未过期 |
| 5 | 注入上下文键 |

### Context 注入键

| 键 | 来源 |
|:---|:---|
| `user_id` | JWT claims |
| `username` | JWT claims |
| `english_name` | JWT claims |
| `phone` | JWT claims |
| `group_name` | JWT claims |
| `role` | JWT claims |
| `dev_role` | JWT claims |
| `status` | JWT claims |

## 限制说明

| TBD/TODO | 说明 |
|:---|:---|
| 刷新接口 | 无，Token 过期需重新登录 |
| 服务端注销 | 无，前端丢弃 Token |
| 登录失败锁定 | 字段存在，逻辑未实现 |
