管理员二次验证登录
1. 接口定位
- 接口名称: 管理员二次验证登录
- 所属域: admin/account
- 业务目标: 使用 challengeID + 校验码完成管理员二次验证,并签发管理员 token
2. 请求定义
- Method:
POST - Path:
/adminx/account/login/totp - Content-Type: 推荐
application/json - operationID: 必填,请通过 Header
operationID传入 - 鉴权: 无(依赖 challengeID)
- 幂等性: 非幂等(challenge 一次成功即销毁,backup code 一次消费)
3. 请求参数
Header 参数
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
| operationID | 是 | string | 链路追踪 ID |
| token | 否 | string | 本接口无需 |
Body 参数
| 字段 | 必填 | 类型 | 说明 |
|---|---|---|---|
| challengeID | 是 | string | 登录第一阶段返回的挑战 ID |
| code | 是 | string | 6 位 TOTP 或 backup code |
4. 响应结构
通用响应包裹
| 字段 | 类型 | 说明 |
|---|---|---|
| errCode | int | 错误码,0 表示成功 |
| errMsg | string | 错误简述 |
| errDlt | string | 错误详情 |
| data | object | 业务数据 |
data 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| needTwoFactor | bool | 固定返回 false |
| adminAccount | string | 管理员账号 |
| adminToken | string | 管理员 token |
| adminUserID | string | 管理员 userID |
| nickname | string | 管理员昵称 |
| faceURL | string | 管理员头像 |
| level | int32 | 管理员等级 |
| imUserID | string | 默认 OpenIM 管理员 ID |
| imToken | string | 默认 OpenIM 管理员 token |
5. 业务规则
challengeID默认 2 分钟有效,过期后不可用。- 二次验证开始前会再次检查当前管理员是否已被封禁;若已封禁则直接拒绝登录。
- 校验码支持两类:
- TOTP 动态码;
- backup code(一次性消费,匹配后即从备份码列表移除)。
- 连续失败达到上限(默认 5 次)会销毁 challenge。
- 校验成功后,challenge 和失败计数会立即删除。
- 本接口会记录最终登录审计:成功时写入成功记录;失败时写入失败原因,例如
invalid totp code或admin blocked。
6. 错误码与失败场景
| 错误码 | 场景 | 典型报错 |
|---|---|---|
| 1001 | Header 缺少 operationID | header must have operationID |
| 1001 | challengeID 为空 | challengeID is empty |
| 1001 | challenge 过期或不存在 | challenge expired or not found |
| 1001 | 校验码错误 | invalid totp code |
| 1001 | 连续失败次数过多 | too many attempts |
| 1002 | 管理员已被封禁 | admin blocked |
| - | challenge 读写失败 | 由 Redis 客户端返回 |
7. 示例
fetch 请求示例
javascript
fetch("http://localhost:10011/adminx/account/login/totp", {
method: "POST",
headers: {
operationID: "adminx-login-totp-001",
"Content-Type": "application/json",
},
body: JSON.stringify({
challengeID: "f5e4f0f4d2f84d6a2b1a0f3f5f6d7c8e",
code: "123456",
}),
})
.then((res) => res.json())
.then((data) => console.log(data));成功响应示例
json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"needTwoFactor": false,
"adminAccount": "root_admin",
"adminToken": "eyJhbGciOi...",
"adminUserID": "1000000001",
"nickname": "System Admin",
"faceURL": "",
"level": 100,
"imUserID": "imAdmin",
"imToken": "eyJhbGciOi..."
}
}失败响应示例
json
{
"errCode": 1001,
"errMsg": "ArgsError",
"errDlt": "invalid totp code"
}8. 时序流程
- 读取 challengeID 对应挑战信息。
- 检查挑战失败次数是否超过上限。
- 校验 TOTP 或 backup code。
- 成功后删除 challenge,签发管理员 token 并返回。
9. 变更记录
- 2026-04-14: 补充管理员封禁拦截与最终登录审计说明。
- 2026-04-07: 首版发布,新增管理员二次验证登录接口文档。