# TOTP双因素认证

<cite>
**Referenced Files in This Document**   
- [totpapi.ts](file://src/api/generated/apis/totpapi.ts)
- [TOTPApi.md](file://src/api/generated/docs/TOTPApi.md)
- [totp.tsx](file://src/views/user-center/user-profile/components/totp.tsx)
- [user.ts](file://src/api/user.ts)
- [kami-api-sys-user-v1-totp-image-get-res.ts](file://src/api/generated/models/kami-api-sys-user-v1-totp-image-get-res.ts)
- [kami-api-sys-user-v1-totp-reset-req.ts](file://src/api/generated/models/kami-api-sys-user-v1-totp-reset-req.ts)
- [kami-api-sys-user-v1-totp-set-req.ts](file://src/api/generated/models/kami-api-sys-user-v1-totp-set-req.ts)
- [kami-api-sys-user-v1-totp-status-get-res.ts](file://src/api/generated/models/kami-api-sys-user-v1-totp-status-get-res.ts)
</cite>

## 目录

1. [简介](#简介)
2. [API端点详解](#api端点详解)
3. [前端组件分析](#前端组件分析)
4. [工作流程](#工作流程)
5. [安全最佳实践](#安全最佳实践)
6. [错误处理与常见问题](#错误处理与常见问题)

## 简介

TOTP（基于时间的一次性密码）双因素认证是一种增强账户安全性的机制，通过结合用户知道的密码和用户拥有的设备（如手机上的认证应用）来验证用户身份。在kami_frontend项目中，TOTP双因素认证系统为用户提供了一层额外的安全保护。

该系统通过四个主要API端点实现：`apiUserTotpImageGet`、`apiUserTotpSetPost`、`apiUserTotpResetPost`和`apiUserTotpStatusGet`，分别用于获取TOTP二维码、设置TOTP认证、重置TOTP认证和查询TOTP状态。前端通过`StepOneForm`和`StepTwoForm`两个组件实现用户交互界面，引导用户完成TOTP的启用和管理。

**Section sources**

- [totpapi.ts](file://src/api/generated/apis/totpapi.ts)
- [totp.tsx](file://src/views/user-center/user-profile/components/totp.tsx)

## API端点详解

### apiUserTotpImageGet

此API端点用于获取TOTP二维码图像，允许用户在认证应用中扫描并添加账户。

**请求参数**

- `code` (string): 验证码，必填

**响应格式**

```json
{
  "image": "base64编码的二维码图像数据"
}
```

**功能说明**
该端点接收用户输入的验证码，验证通过后返回一个包含TOTP密钥的二维码图像。用户可以使用Google Authenticator等认证应用扫描此二维码，将账户添加到应用中。

**Section sources**

- [totpapi.ts](file://src/api/generated/apis/totpapi.ts#L62-L77)
- [kami-api-sys-user-v1-totp-image-get-res.ts](file://src/api/generated/models/kami-api-sys-user-v1-totp-image-get-res.ts#L19-L26)

### apiUserTotpSetPost

此API端点用于设置并启用TOTP双因素认证。

**请求参数**

- `code` (string): 验证码，必填
- `password` (string): 用户密码，必填
- `otpKey` (string): OTP密钥，必填
- `otpSecret` (string): OTP密钥秘密，必填

**响应格式**

- HTTP状态码200表示成功

**功能说明**
该端点接收用户在认证应用中生成的验证码、用户密码以及TOTP密钥信息，验证所有信息正确后，将TOTP认证设置为启用状态，完成双因素认证的配置。

**Section sources**

- [totpapi.ts](file://src/api/generated/apis/totpapi.ts#L168-L185)
- [kami-api-sys-user-v1-totp-set-req.ts](file://src/api/generated/models/kami-api-sys-user-v1-totp-set-req.ts#L19-L44)

### apiUserTotpResetPost

此API端点用于重置或删除已设置的TOTP双因素认证。

**请求参数**

- `code` (string): 验证码，必填

**响应格式**

```json
{
  // 响应内容根据实际实现而定
}
```

**功能说明**
该端点允许用户通过提供有效的验证码来重置TOTP认证。执行此操作后，用户的TOTP设置将被清除，双因素认证将被禁用，用户下次登录时将不再需要提供TOTP验证码。

**Section sources**

- [totpapi.ts](file://src/api/generated/apis/totpapi.ts#L134-L151)
- [kami-api-sys-user-v1-totp-reset-req.ts](file://src/api/generated/models/kami-api-sys-user-v1-totp-reset-req.ts#L19-L26)

### apiUserTotpStatusGet

此API端点用于查询当前用户的TOTP认证状态。

**请求参数**

- 无

**响应格式**

```json
{
  "status": true,
  "image": "base64编码的二维码图像数据",
  "otpSecret": "OTP密钥秘密",
  "otpKey": "OTP密钥"
}
```

**功能说明**
该端点返回当前用户的TOTP认证状态信息，包括是否已启用TOTP认证，以及相关的密钥信息。如果TOTP未启用，还会返回用于设置TOTP的二维码图像。

**Section sources**

- [totpapi.ts](file://src/api/generated/apis/totpapi.ts#L202-L219)
- [kami-api-sys-user-v1-totp-status-get-res.ts](file://src/api/generated/models/kami-api-sys-user-v1-totp-status-get-res.ts#L19-L44)

## 前端组件分析

### StepOneForm组件

`StepOneForm`组件用于处理TOTP认证的启用流程，当用户尚未启用TOTP时显示。

**用户交互流程**

1. 显示由后端生成的TOTP二维码，用户使用认证应用扫描
2. 要求用户输入账户密码进行身份验证
3. 要求用户输入认证应用生成的6位验证码
4. 提交表单，调用`apiUserTotpSetPost`API完成TOTP设置

**组件属性**

- `QrImage`: 二维码图像的base64数据
- `otpKey`: OTP密钥
- `otpSecret`: OTP密钥秘密

**功能实现**
该组件通过表单验证确保用户输入了必要的信息，然后调用`setTotp`函数发送设置请求。成功后触发`submit`事件，通知父组件更新状态。

**Section sources**

- [totp.tsx](file://src/views/user-center/user-profile/components/totp.tsx#L102-L144)

### StepTwoForm组件

`StepTwoForm`组件用于管理已启用的TOTP认证，当用户已启用TOTP时显示。

**用户交互流程**

1. 提供"查看两步验证"按钮，点击后显示TOTP二维码图像
2. 提供"删除两步验证"按钮，点击后调用`apiUserTotpResetPost`API重置TOTP
3. 需要输入验证码才能执行上述操作

**功能实现**
该组件允许用户查看当前的TOTP配置或完全重置TOTP认证。通过`getTotpImage`函数获取二维码图像，通过`resetTotp`函数重置认证设置。

**Section sources**

- [totp.tsx](file://src/views/user-center/user-profile/components/totp.tsx#L49-L101)

## 工作流程

```mermaid
sequenceDiagram
participant 用户
participant 前端
participant 后端
用户->>前端 : 访问用户中心
前端->>后端 : 调用apiUserTotpStatusGet
后端-->>前端 : 返回TOTP状态
alt TOTP未启用
前端->>用户 : 显示StepOneForm
用户->>前端 : 扫描二维码并输入密码和验证码
前端->>后端 : 调用apiUserTotpSetPost
后端-->>前端 : 返回设置结果
前端->>用户 : 显示启用成功
else TOTP已启用
前端->>用户 : 显示StepTwoForm
用户->>前端 : 点击"查看两步验证"
前端->>后端 : 调用apiUserTotpImageGet
后端-->>前端 : 返回二维码图像
前端->>用户 : 显示二维码
用户->>前端 : 点击"删除两步验证"
前端->>后端 : 调用apiUserTotpResetPost
后端-->>前端 : 返回重置结果
前端->>用户 : 显示重置成功
end
```

**Diagram sources**

- [totpapi.ts](file://src/api/generated/apis/totpapi.ts)
- [totp.tsx](file://src/views/user-center/user-profile/components/totp.tsx)

**Section sources**

- [totp.tsx](file://src/views/user-center/user-profile/components/totp.tsx)

## 安全最佳实践

### 验证码时效性

系统应确保TOTP验证码具有适当的时效性，通常为30秒。这可以防止重放攻击，即使攻击者截获了验证码，也很难在有效期内使用。

### 尝试次数限制

为防止暴力破解，系统应对TOTP验证码的尝试次数进行限制。建议实现以下机制：

- 连续失败5次后锁定账户15分钟
- 记录失败尝试日志用于安全审计
- 发送通知提醒用户异常登录尝试

### 密钥安全存储

TOTP密钥的安全存储至关重要：

- 密钥应在传输过程中使用HTTPS加密
- 服务器端应安全存储密钥，最好进行加密处理
- 前端不应长期缓存密钥信息
- 用户密码在传输前应进行加密处理

### 其他安全建议

- 提供备用验证方法，如恢复码，以防用户丢失认证设备
- 在敏感操作时要求重新验证TOTP
- 定期提醒用户检查和更新其TOTP设置
- 提供详细的登录活动日志，让用户监控账户安全

**Section sources**

- [user.ts](file://src/api/user.ts)
- [totp.tsx](file://src/views/user-center/user-profile/components/totp.tsx)

## 错误处理与常见问题

### 二维码无法扫描

**可能原因**

- 二维码图像加载失败
- 屏幕分辨率导致二维码显示不完整
- 光线条件不佳影响扫描

**解决方案**

- 检查网络连接，重新加载页面
- 调整屏幕亮度和对比度
- 尝试在不同光照条件下扫描
- 使用"查看两步验证"功能获取新的二维码图像

### 验证码无效

**可能原因**

- 设备时间与服务器时间不同步
- 输入了错误的验证码
- 验证码已过期（超过30秒）

**解决方案**

- 确保设备时间设置正确，最好启用自动时间同步
- 重新输入当前显示的验证码
- 等待新的验证码生成后再次尝试
- 检查认证应用中的账户配置是否正确

### TOTP设置失败

**可能原因**

- 密码输入错误
- 验证码输入错误
- 网络连接问题

**解决方案**

- 确认密码正确无误
- 确保在验证码有效期内完成输入
- 检查网络连接，重试操作
- 如问题持续存在，联系系统管理员

### 其他常见问题

**问题：无法重置TOTP认证**

- 确保输入了正确的当前验证码
- 检查账户是否有足够的权限执行此操作
- 尝试刷新页面后重试

**问题：TOTP状态显示不正确**

- 刷新页面以获取最新状态
- 清除浏览器缓存
- 检查网络连接是否稳定

**Section sources**

- [totp.tsx](file://src/views/user-center/user-profile/components/totp.tsx)
- [user.ts](file://src/api/user.ts)
