Files
wecom_it_smart_desk/docs/02-技术文档/技术方案-REQ-认证-统一认证与登录-v1.0.md
T
Simon facc04aa65 chore: docs 结构整改 + compose 双目录对齐(合并重建提交)
本提交为 .git 对象库损坏后的重建提交,内容等价于原先三个本地提交
(5e2fd4c2 / 57a53c98 / 5d7e1873)的累积结果,未做任何额外改动。

一、docs 结构整改(整改 #14)
根因:重构时新结构为 untracked 文件,执行 git stash(未带 -u)未纳入,
随后 git reset 拉回 HEAD 旧 tracked 树,导致旧树复活、新旧两棵目录
树并存于 docs/,共 791 文件、双分类体系冲突。

修复动作:
- b2 同名异主题文件改名迁移保全 9 个
- C 类 39 个孤立文件按主题正确归类
- A/B1 类 222 个重复文件删除(新结构已有内容副本)
- 9 个旧独有空目录删除
- 270 处内部引用按 verified 映射改写
- 整改记录 #14 登记于 04-运维文档/部署运维

结果:docs 791 → 569 文件,顶层仅规范 8 类 + 治理文件,单树恢复。
残留:约 20 处指向从未存在文件的陈旧死链,归入独立文档卫生任务。

二、compose 双目录对齐(消除踩坑 A)
- docker-compose.yml:nginx 前端挂载全部由根目录 frontend-*/dist
  改为 src/frontend-*/dist(h5 / agent / admin / terminal)
- docker-compose.dev.yml:dev 服务 build context 与卷同步改 src/
- 效果:本地 docker compose up 不再把根目录 stale dist 挂回,
  与线上一致,分叉隐患消除(已 docker compose config 校验通过)

防复发铁律:
- 重构须提交;仓库修复须 git stash -u 或先 commit
- 新结构须 git add 并提交,避免再次 untracked 复活
- H5 改动只动 src/frontend-h5/,禁改根目录遗留 frontend-*/
2026-08-07 22:31:32 +08:00

187 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 技术方案-REQ-认证-统一认证与登录
> **版本**: v1.0 | **日期**: 2026-08-05 | **状态**: 预研整合(与 PRD v1.1 对齐)
> **作者**: 宋献(产品)/ 技术评审:—
> **关联文档**:
> - PRD`../01-产品文档/01-认证与登录/PRD-REQ-认证-统一认证与登录-v1.1.md`
> - 测试用例:`../03-测试文档/03-功能测试用例/TC-REQ-认证-统一认证与登录-v1.0.md`
> - OTP 运维:`部署运维/06-OTP二次验证实现.md`
> - 扫码+OTP 部署:`部署运维/07-扫码登录OTP部署指南-v0.7.0.md`
> - 管理端登录序列:`技术架构/05-架构图/admin-login-sequence.mermaid`
---
## 1. 背景与目标
本技术方案是认证与登录模块的**技术单一真源**,与 PRD v1.1、测试用例 v1.0 形成「三件套」。
目标:
1. 收敛散落在运维/测试/架构文档中的认证技术设计,统一到 `02-技术文档`
2. 明确各通道的接口契约、数据模型与认证强度约束;
3. 为 REQ-认证-003(坐席端一键免登录)提供设计预研;
4. 为 REQ-认证-004(管理端一键免登录)保留设计边界(**不立项**)。
---
## 2. 认证能力现状(技术视角)
### 2.1 扫码登录(REQ-认证-001,已上线 v0.7.0
| 项 | 内容 |
|---|---|
| 后端端点 | `/api/auth_qrcode/*`v0.7.0 新增 4 个端点) |
| 前端 | `frontend-agent/src/views/Login.vue``frontend-admin/src/views/Login.vue` 重写扫码 UI`frontend-portal/src/views/QrcodeLogin.vue` |
| 安全属性 | 双信道分离(手机认证 ≠ PC 操作)+ 人工主动扫码 = 弱 2FA / 带外确认 |
| 部署 | 见 `部署运维/07-扫码登录OTP部署指南-v0.7.0.md` |
### 2.2 账号绑定(REQ-认证-002,已上线)
- 坐席首次通过企微身份登录后,后端将其企微 `userid` 与系统 `agent` 账号建立绑定关系(写入 `agents` / 角色关联表)。
- 绑定是「一键免登录」「角色校验」「OTP 启用」的共同前置条件。
### 2.3 OTP / MFA 二次验证(已上线 v0.7.0
| 项 | 内容 |
|---|---|
| 机制 | TOTPpyotp / Google Authenticator),SMS(蜂鸟)作为备用通道 |
| 数据模型 | `users.mfa_secret``users.mfa_enabled``users.mfa_bound_at``users.mfa_last_verified_at` |
| 后端接口 | `/api/auth/otp-*`6 个端点,见 `app/api/otp.py`)、`/api/auth/otp-admin-reset/{employee_id}`(管理员重置)、`/api/admin/high-risk/*`(高危操作 OTP 守卫 `require_high_risk_otp` |
| 登录流程 | admin 角色且 `mfa_enabled=1` 时,登录返回 `require_otp: True`,前端显示 OTP 输入框,验证通过才签发 token |
| 角色差异 | 坐席 OTP **可选**(绑定后启用);admin OTP **强制常驻第二因子** |
| 错误码 | 1006/1007/1008/1009/1010OTP 相关) |
> ⚠️ **文档一致性提示(2026-08-05 更新)**`部署运维/06-OTP二次验证实现.md` 原使用 v0.5.6 旧命名 `/api/agents/otp-*`,已于 2026-08-05 修正为当前生产实现 **`/api/auth/otp-*`**(路由文件 `app/api/otp.py`prefix=`/auth`)。部署指南 `07-扫码登录OTP部署指南-v0.7.0.md`、测试用例 `TC-REQ-认证-统一认证与登录-v1.0.md` 与前端 `frontend-agent/src/api/mfa.ts` 端点调用中原引用的更早规划命名 `/api/mfa/*`,已在本轮(2026-08-05)一并修正为 `/api/auth/otp-*`AUTH-03 重构已用其取代原 `/mfa/*` 与 `/admin/mfa/*`)。当前活跃文档与实现已一致。
### 2.4 企微 JS-SDK 免登录(`jsdk-login`,现成半截)
| 项 | 内容 |
|---|---|
| 接口 | `POST /api/auth_wecom/jsdk-login` |
| 行为 | 传入企微 `userid` → 后端查角色 → 直接返回 tokenagent / admin / user |
| 现状 | 已在测试用例 JSDK-01~05 覆盖,是「一键免登录」后端的**现成半截**——缺前端在登录页主动拿 `userid` 的环节 |
| 风险点 | 历史上 `EmergencyDispatcher.vue:113` 曾用未赋值的 `window.wecom_userid` 全局变量,导致拿不到 userid;**userid 必须来自标准 SDK 调用,禁止依赖全局变量** |
### 2.5 管理端登录基础序列
`技术架构/05-架构图/admin-login-sequence.mermaid` 描述基础序列:`/api/agents/login`user_id + name)→ DB 查 role → Redis 存 token → 前端校验 `role==="admin"` → 存 `admin_token` → 跳转 `/admin/dashboard`。注意:该序列为 OTP 启用前的基础流,生产流已叠加 §2.3 的 OTP 步骤。
---
## 3. 接口契约汇总
| 通道 | 端点 | 说明 |
|---|---|---|
| 扫码登录 | `/api/auth_qrcode/*`4 端点) | v0.7.0 新增 |
| 企微免密 | `POST /api/auth_wecom/jsdk-login` | 传 userid → 返回 token |
| 账号密码 | `POST /api/agents/login` | 坐席/管理员账号密码 + OTP |
| OTP | `/api/auth/otp-*`(6 端点) | 绑定/验证/解绑等(见 `app/api/otp.py` |
| OTP 重置 | `POST /api/auth/otp-admin-reset/{employee_id}` | 管理员重置 |
| 高危守卫 | `/api/admin/high-risk/*` + `require_high_risk_otp` | 高危操作 OTP 守卫 |
| 一键(预研) | `POST /api/auth/check-wecom-bind?userid=&role=agent`(待建) | REQ-003 新增 |
**数据模型关键字段**`agents.userid`(企微绑定)、`users.mfa_secret/enabled/bound_at/last_verified_at``role`agent/admin/user)。
---
## 4. 认证强度分级技术约束(对应 PRD §3)
以「风险敞口」而非「功能对称」分配认证强度:
| 通道 | 技术约束 |
|---|---|
| 扫码登录 | 基准通道,始终保留;双信道弱 2FA |
| 一键免登录(agentConfig | **仅坐席端**;仅 PC 端、仅已绑定用户;token 有效期 < 8h(建议 24h + refresh);复用 `jsdk-login` 签发 |
| 管理端登录 | OTP 常驻强制第二因子;**不套用一键免登录** |
| 管理端一键(未来) | **不立项**;若未来立项,OTP 必须作为前置强制第二因子 |
---
## 5. REQ-认证-003 坐席端一键免登录 — 设计预研
### 5.1 总体时序
```
登录页加载
→ isWecomEnv()?(UA 含 wxwork)
否 → 走原扫码
是 → wx.config + wx.agentConfig(with_agent_config=true) 拿 userid
→ POST /api/auth/check-wecom-bind?userid=&role=agent
has_bind=true → 显示「一键登录」→ 复用 jsdk-login 签发 token → 工作台
has_bind=false → 回落扫码 + 提示语
```
### 5.2 前端断点
- 文件:`frontend-agent/src/views/Login.vue`
- 在现有 `isWecomEnv()` 分支内补齐 `wx.agentConfig` 调用链(签名复用 `wecom_jsapi.py``with_agent_config=true`,见 `wecom_jsapi.py:33`)。
- `userid` 必须来自 `wx.agentConfig` 回调,**禁止 `window.wecom_userid`**。
- UI:校验通过显示「🟢 一键登录」按钮;失败静默回落扫码。
### 5.3 后端断点
- 新增 `POST /api/auth/check-wecom-bind`(参数 `userid` + `expected_role=agent`),返回 `has_bind` + `role`
- 一键签发复用 `jsdk-login` 的 userid→token 逻辑(不新建签发路径)。
- H5 端无需改动(员工本就在企微内运行)。
### 5.4 安全约束
- 仅对**已绑定用户**开放;token 有效期短于 8h(建议 24h + refresh)。
- 失败/异常一律回落扫码,不影响存量用户。
- 不引入 `window.wecom_userid` 全局变量(历史 bug 教训)。
### 5.5 复用关系
- 复用:`isWecomEnv()`Login.vue 已有)、`wecom_jsapi.py` 签名、`jsdk-login` 签发、角色校验表。
- 新增:仅 `check-wecom-bind` 一个接口 + Login.vue 的 agentConfig 调用与 UI。
---
## 6. REQ-认证-004 管理端一键免登录 — 设计预留(不立项)
**决策(2026-08-05Q3**:**不立项**。管理端风险敞口(系统配置/权限/全局数据)远大于坐席端,按 §4 分级不套用一键免登录。
仅作未来设计边界预留(不进入排期):
- 若未来立项,必须复用 REQ-003 的企微身份探测 + 将既有 OTP(`/api/auth/otp-*`)作为**前置强制第二因子**
- 新增部分仅为「企微身份一键探测 + 复用既有 OTP 作前置网关」,非从零建设 OTP。
---
## 7. 非目标
1. REQ-003 仅预研,本次不开发;
2. 管理端一键(REQ-004)不立项;
3. 不改变扫码登录(基准通道);
4. 不新建 OTP 体系(复用既有 `/api/auth/otp-*`);
5. 不涉及 H5 登录改造。
---
## 8. 风险与缓解
| 风险 | 缓解 |
|---|---|
| 单设备被控 → 攻击者可无手机配合新发起会话 | 仅已绑定用户 + 短时效 token + 设备绑定(P2 |
| agentConfig 调用失败 | 静默回落扫码 |
| `window.wecom_userid` 未赋值 | 禁止全局变量,强制标准 SDK 调用 |
| 06 文档端点命名偏差(旧 `/api/agents/otp-*` | 已于 2026-08-05 修正为生产实现 `/api/auth/otp-*`;07 部署指南/TC 测试用例/前端 `mfa.ts` 端点调用中的 `/api/mfa/*` 规划命名亦于本轮(2026-08-05)一并修正,活跃文档与实现已一致 |
---
## 9. 关联文档索引
| 文档 | 路径 | 用途 |
|---|---|---|
| PRD | `../01-产品文档/01-认证与登录/PRD-REQ-认证-统一认证与登录-v1.1.md` | 产品需求 |
| 测试用例 | `../03-测试文档/03-功能测试用例/TC-REQ-认证-统一认证与登录-v1.0.md` | 功能用例 |
| OTP 实现 | `部署运维/06-OTP二次验证实现.md` | OTP 机制(端点命名待对齐) |
| 扫码+OTP 部署 | `部署运维/07-扫码登录OTP部署指南-v0.7.0.md` | 部署与现状 |
| admin 登录序列 | `技术架构/05-架构图/admin-login-sequence.mermaid` | 序列图 |
---
## 10. 修订历史
| 版本 | 日期 | 变更内容 | 修改人 |
|---|---|---|---|
| v1.0 | 2026-08-05 | 初始技术方案:收敛认证技术设计、接口契约、认证强度分级约束、REQ-003 设计预研、REQ-004 不立项边界 | 宋献 |