Files
nexus/Project/fonrey/PRD/登录管理/用户登录管理模块PRD.md
2026-05-02 11:35:20 +08:00

683 lines
42 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.
# PRD用户登录管理模块
**状态**: Draft
**作者**: 产品经理
**最后更新**: 2026-05-02v3.0 按 `ADR-20260502-003` 重写:剥离全部实现细节——具体 API 路径、HTTP 方法、JSON Schema、Redis Key、字段类型、Electron API 名、Cookie 属性、限流接口实现等——交由 Tech / DATA_MODEL 承接;本文件只保留业务能力、页面与导航、业务规则、状态机、验收标准)
**版本**: 3.0
**所属系统**: Fonrey 房产经纪管理系统
**关联模块**: 组织人事管理、权限管理、平台管理后台
## 关联文档(实现口径)
- 实现细节端点路径、HTTP 方法、JSON Schema、错误码、滑块/OTP 算法、限流策略、Electron 客户端约定):`TECH_STACK/登录管理技术方案.md`v4.1
- 数据结构(账号表、登录审计表、短信 OTP 表、历史密码表、Redis Key 命名、字段类型与索引):`DATA_MODEL/DATA_MODEL_LOGIN.md`
- 全局 API 契约(统一错误响应、分页、限流外显规范):`TECH_STACK/API_CONTRACT.md`
- 测试用例:`TEST_CASES/TEST_CASES_LOGIN_MODULE.md`
> 本 PRD 涉及的"具体路径 / 字段名 / Token TTL 数值 / Cookie 属性 / Redis Key / 框架 API 名"等实现口径,**均不在本文件出现**,请按上表查阅对应权威文档。
## 变更历史
| 版本 | 日期 | 作者 | 变更说明 |
| ---- | ---------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| v1.x | — | 产品经理 | 初稿至 v1.9(详见 git 历史) |
| v2.0 | 2026-04-30 | 产品经理 | 根据 review 后的 §4 用户故事全面同步 §5 功能详细说明:删除找回用户名流程及邮件模板;找回密码改为纯短信流程;新增 §5.5 手机验证码登录详细说明§6 技术注意事项更新短信依赖/风险/开放问题§8.2 接口清单同步正式功能状态全文「Tenant ID」对外概念统一替换为「Tenant Code」 |
| v3.0 | 2026-05-02 | Sisyphus | 按 `ADR-20260502-003` 重写:剥离全部实现细节交由 Tech / DATA_MODEL 承接;删除 §5.1.4 接口规范代码块、§5.2.2 Redis Key 与传输层细节、§5.3.3 字段类型表、§5.6 数据模型字段清单、§5.7 Electron 客户端约定、§6.1 依赖技术选型表、§6.2 多租户实现细节、§8.2 接口清单汇总;保留页面/导航/业务规则/状态机/验收标准;具体口径全部以 `TECH_STACK/登录管理技术方案.md` 为准 |
---
## 1. 问题陈述
### 1.1 背景
Fonrey 是一套面向房产经纪公司的 B2B SaaS 平台,采用多租户架构,每家经纪公司是一个独立租户。终端用户通过 **Windows 桌面客户端Electron 壳应用)** 使用系统,无需手动输入网址即可打开 Web 应用。
在多租户环境下,用户的身份验证流程比单租户系统更复杂:
- 用户安装客户端后,系统必须先识别当前设备归属哪个租户,才能加载对应租户的登录界面和数据隔离环境
- 每家经纪公司作为独立租户,其员工账号、组织结构、数据均完全隔离
- 经纪人账号须与实名员工档案绑定,确保每一条操作记录可追溯至具体自然人
- 现阶段登录方式以账号密码与手机验证码为主;微信扫码登录需预留入口,待移动端(小程序)上线后实现
### 1.2 核心痛点
| 痛点 | 影响方 | 当前代价 |
|------|--------|---------|
| 多租户环境下,客户端不知道应该连接哪个租户的服务端 | 新用户首次安装后无法正常使用 | 系统无法启动,用户体验极差 |
| 账号密码裸露登录,缺乏验证码保护 | 所有用户 | 存在暴力破解、自动化恶意登录风险 |
| 用户忘记密码无自助找回通道 | Agent经纪人 | 依赖管理员手动重置,效率低 |
| 账号未与实名经纪人档案绑定 | Tenant Admin租户管理员、合规审计 | 操作行为无法追溯至自然人 |
| 无多因素认证,安全系数低 | 管理层、数据合规 | 存在账号冒用、数据泄露风险 |
### 1.3 目标用户
| 角色 | 描述 | 使用频率 |
|------|------|----------|
| Agent经纪人 | 每日登录系统使用房源/客源功能 | 每日高频 |
| 店长 / 经理 | 登录后查看全店数据、管理任务 | 每日 |
| Tenant Admin租户管理员 | 管理账号创建、密码重置、租户初始化 | 按需 |
| 新安装用户 | 首次安装客户端后需完成 Tenant 识别 | 一次性 |
---
## 2. 目标与成功指标
| 目标 | 指标 | 当前基准 | 目标值 | 衡量周期 |
|------|------|----------|--------|----------|
| 降低登录失败率 | 账号密码正确情况下的登录成功率 | 待统计 | ≥ 99% | 上线后 30 天 |
| 防止恶意登录 | 每日验证码拦截异常登录请求数 | 0无保护 | 建立基线,对同 IP 异常突增触发封锁 | 上线后持续监控 |
| 提升找回账号效率 | 用户自助找回密码耗时 | 依赖管理员(约 1 工作日) | < 3 分钟(短信验证码自助) | 上线后 30 天 |
| 确保账号实名绑定率 | 拥有系统账号且未与员工档案绑定的账号比例 | 待统计 | 0%(强制绑定) | 上线即达标 |
| Tenant 识别成功率 | 首次安装后成功完成 Tenant 识别的用户比例 | 待统计 | ≥ 98% | 上线后 30 天 |
> 具体的同 IP 限流阈值与 Tenant Code 校验频控数值,详见 `TECH_STACK/登录管理技术方案.md`。
---
## 3. 非目标(本期不做)
- **微信扫码登录**:移动端小程序上线后实现,本期**仅在登录页保留禁用入口**,不开放实际功能
- **单点登录SSO/ 企业微信集成**:后续版本规划
- **多设备并发登录的强制踢出策略**:本期允许同账号多端登录,后续安全策略模块规划
- **登录时段限制 / IP 白名单**:安全策略模块另行规划
- **平台管理后台Platform Admin登录**:属于平台管理后台模块,本 PRD 专注租户内用户登录
- **找回用户名流程**普通员工用户名固定为手机号无需找回Tenant Admin 如忘记用户名请联系平台运营线下处理(原 Story 4 已废弃)
---
## 4. 页面清单与导航
> 本节描述用户视角的页面与跳转关系;具体的前端路由实现与 URL 形态由 `TECH_STACK/登录管理技术方案.md` 定义。
### 4.1 页面清单
| 页面 | 访问权限 | 用途 |
|---|---|---|
| Tenant 识别页 | 公开(无需登录) | 客户端首次启动或切换公司时输入租户识别码 |
| 登录页 | 公开(需先完成 Tenant 识别) | 提供「密码登录」/「验证码登录」两种方式,含微信扫码禁用入口 |
| 找回密码页(三步) | 公开 | 输入手机号 → 输入短信验证码 → 设置新密码 |
| 首次登录强制改密页 | 已登录且账号处于初始密码状态 | 强制用户修改初始密码后方可使用系统 |
| 系统首页 | 已登录且非初始密码状态 | 业务入口;不在本 PRD 范围 |
### 4.2 导航流程
```
[客户端启动]
├─ 本地无 Tenant 缓存 ──→ [Tenant 识别页]
│ │ 验证成功
│ ↓
│ 缓存 Tenant ──→ [登录页]
└─ 本地有 Tenant 缓存 ──→ [登录页]
[登录页]
├─ 密码 / 验证码登录成功
│ │
│ ├─ 账号为"初始密码"状态 ──→ [首次登录强制改密页] ──改密成功──→ [系统首页]
│ └─ 账号为"非初始密码"状态 ──→ [系统首页]
├─ 点击"忘记密码" ──→ [找回密码页(步骤一)] → [步骤二] → [步骤三] ──→ 回 [登录页]
└─ 点击"切换公司"(二次确认)──→ 清缓存 ──→ [Tenant 识别页]
[系统内]
├─ 主动登出 ──→ [登录页]
├─ Session 过期 ──→ [登录页](提示"登录已过期,请重新登录"
└─ 客户端版本过低 ──→ [更新提示页] → 阻断后续登录流程
```
---
## 5. 用户故事与验收标准
### Story 1新用户首次启动客户端——Tenant 识别
**As** 新安装 Fonrey 客户端的经纪人,**I want** 在首次启动时输入所属公司的 12 位 Tenant Code 完成租户识别,**So that** 客户端能连接到正确的服务端,后续显示对应公司的登录界面和数据。
**验收标准**
- [ ] 客户端首次启动时(本地无 Tenant Code 缓存自动呈现「Tenant 识别」页面,而非直接显示登录页
- [ ] 页面包含:产品 Logo、产品名称「Fonrey 房睿」、说明文案「请输入您公司的专属识别码」、Tenant Code 输入框、「确认」按钮、帮助文案「不知道识别码请联系您公司的Tenant Admin租户管理员
- [ ] Tenant Code 输入框支持粘贴操作,自动去除前后空格,仅接受数字字符(非数字自动过滤),固定 12 位
- [ ] 点击「确认」后展示加载状态spinner由客户端向服务端发起 Tenant 验证
- [ ] **验证成功**服务端返回租户名称及品牌信息公司名称、Logo 等);客户端将 Tenant Code 持久化到本地必须加密存储自动跳转至该租户的登录页登录页顶部展示「正在登录XX 房产」
- [ ] **验证失败**(识别码无效):输入框下方显示红色错误提示「识别码无效,请联系您的 Tenant Admin租户管理员获取正确的识别码」Tenant Code 不写入本地缓存;用户可重新输入
- [ ] **网络异常**:显示「网络连接失败,请检查网络后重试」,提供「重试」按钮
- [ ] 非首次启动(本地已有合法 Tenant Code 缓存):直接跳过识别页,进入登录页
- [ ] 登录页提供「切换公司」入口(链接文字,非主要 CTA点击后弹出二次确认「切换公司将退出当前账号是否继续确认后清除本地 Tenant Code 缓存并重新显示 Tenant 识别页
- [ ] Tenant 验证为公开操作,无需登录态,但平台需对该接口做防枚举的频控保护(具体阈值见 Tech 文档)
**Tenant Code 业务规则**
- 格式12 位纯数字
- 生成:由平台运营在平台管理后台开通租户时自动生成,全局唯一,不允许手动指定
- 唯一性:全局唯一,同一 Tenant Code 不得分配给多个租户
- 客户端存储:必须加密落盘,禁止明文(实现细节见 Tech 文档 §十三 Electron 客户端约定)
---
### Story 2经纪人通过手机号和密码登录
**As** 已识别租户的经纪人,**I want** 通过手机号和密码完成登录,**So that** 进入系统开始工作。
> **说明**:普通员工的登录账号即为其手机号(由 Tenant Admin 在新增员工时自动创建无需记忆额外用户名。Tenant Admin 账号的登录名为该租户联系人手机号,规则一致。
**验收标准**
- [ ] 登录页展示:租户品牌标识(公司 Logo + 公司名称)、登录方式 Tab「密码登录」/「验证码登录」,默认选中「密码登录」)、手机号输入框、密码输入框、滑块拼图验证区域、「登录」按钮、「忘记密码」链接、「切换公司」入口、微信扫码禁用入口
- [ ] 手机号输入框 Placeholder「请输入您的手机号」仅接受数字字符非数字自动过滤固定 11 位
- [ ] 密码输入框默认密文显示,右侧提供「显示/隐藏」图标切换明密文
- [ ] **行为验证码(滑块拼图)**:展示一张带缺口的背景图和一块可拖动的拼图碎片,用户通过拖动滑块将碎片移动至缺口位置完成验证;无需输入任何字符
- [ ] 验证失败(位置不准或轨迹异常):拼图区域抖动提示,自动刷新新背景图,用户重新拖动;**不计入账号密码错误次数**
- [ ] 验证成功后,拼图区域显示绿色对勾 + 「验证通过」文案,状态持续至本次登录提交完成
- [ ] 提供「刷新」图标按钮,允许用户主动刷新背景图
- [ ] 三项(手机号、密码、滑块)均完成后,「登录」按钮才可点击(否则置灰)
- [ ] 点击「登录」触发前端格式校验:
- 手机号为空 → 提示「请输入手机号」
- 手机号不满 11 位 → 提示「请输入完整的 11 位手机号」
- 密码为空 → 提示「请输入密码」
- 滑块未完成 → 提示「请完成滑块验证」
- [ ] 格式校验通过后提交登录,按钮进入 loading 状态防止重复提交
- [ ] **登录成功**
- 若账号处于"非初始密码"状态:直接进入系统首页,顶部显示欢迎信息「欢迎回来,{姓名}」
- 若账号处于"初始密码"状态:**立即跳转至「首次登录强制改密页」**,不可关闭、不可跳过、不可访问其他功能页面(详见 §6.4
- [ ] **登录失败(手机号或密码错误)**:显示「手机号或密码错误,请重新输入」(不区分具体原因,防止枚举攻击);滑块自动刷新;密码输入框清空;手机号保留
- [ ] **登录失败(滑块异常)**:显示「验证码有误,请重新输入」;滑块自动刷新
- [ ] **账号被锁定**(同一账号密码连续错误达到上限):显示「账号已被临时锁定,请稍后再试,或联系管理员解锁」;锁定状态下「登录」按钮置灰
- [ ] **账号已停用**:显示「账号已停用,请联系您的管理员」
- [ ] **Session 过期**:用户在系统内操作时 Session 过期,自动跳转至登录页,并提示「登录已过期,请重新登录」
**业务规则**(具体数值口径见 Tech 文档):
- 同一账号密码连续错误达到上限后,账号进入临时锁定状态,到期自动解锁;管理员可手动解锁
- 滑块验证失败不计入密码错误次数
- 所有登录请求强制 HTTPS
---
### Story 3经纪人找回密码
**As** 忘记密码的经纪人,**I want** 通过手机号 + 短信验证码完成身份核验,重新设定密码,**So that** 无需邮箱、无需联系管理员,独立完成密码重置。
> **说明**:考虑到大多数经纪人没有常用邮箱,本期找回密码统一通过短信验证码实现,废弃邮箱找回方式。账号中邮箱字段在本系统无任何必须业务用途,完全可选。
**验收标准**
- [ ] 点击登录页「忘记密码」链接,跳转至「找回密码」流程(分三步)
**步骤一:输入手机号**
- [ ] 页面显示手机号输入框11 位数字,自动过滤非数字)、「获取验证码」按钮、「返回登录」链接
- [ ] 手机号为空或不足 11 位 → 点击「获取验证码」时输入框下方提示「请输入完整的 11 位手机号」
- [ ] 手机号格式合法后,点击「获取验证码」,按钮进入 60 秒倒计时冷却态(「重新获取(59s)」),倒计时结束后按钮恢复可点击
- [ ] 不论该手机号是否注册,前端文案统一显示「如该手机号已注册,验证码将在 1 分钟内发送」(**不泄露账号是否存在**
- [ ] 后台仅在手机号存在且账号处于可用状态时实际发送短信
- [ ] 同一手机号在一段时间窗口内发送次数有上限,超限后提示「发送次数过多,请稍后再试」
- [ ] 短信内容模板「【Fonrey 房睿】您的密码重置验证码为 {code}10 分钟内有效,请勿泄露。」
**步骤二:输入短信验证码**
- [ ] 页面显示6 位验证码输入框(支持分格输入)、「重新发送」倒计时链接、「下一步」按钮
- [ ] 「下一步」按钮6 位验证码全部输入后方可点击
- [ ] 校验结果:
- 正确且未过期 → 进入步骤三
- 错误 → 提示「验证码有误,请重新输入」;同一验证码连续错误达到上限后作废,需重新获取
- 已过期 → 提示「验证码已过期,请重新获取」
**步骤三:重置密码**
- [ ] 步骤三依赖步骤二颁发的一次性凭证;凭证无效或过期 → 显示「操作已超时,请重新发起找回密码」,跳回步骤一
- [ ] **本页面复用「设置新密码」公共组件**(与首次登录强制改密页为同一组件,详见 §6.4),保持 UI 与交互逻辑完全一致;入口上下文不同时,仅页面标题与提示文案差异:
| 元素 | 首次登录强制改密§6.4 | 找回密码步骤三(本 Story |
|------|--------------------------|--------------------------|
| 页面标题 | 「欢迎使用 Fonrey请先设置您的登录密码」 | 「重置您的登录密码」 |
| 提示文案 | 「您当前使用的是初始密码,为保障账号安全,请立即设置新密码后开始使用」 | 「请输入您的新密码,设置完成后请使用新密码重新登录」 |
| 提交按钮文案 | 「确认并进入系统」 | 「确认重置密码」 |
| 提交后跳转 | Session 保持,直接进入首页 | 该账号所有 Session 立即失效,跳转登录页并提示「密码已重置,请使用新密码登录」 |
- [ ] 提交成功后:账号"初始密码"标记置为否(找回密码属于用户主动操作,已完成身份核验,**不应再触发首次登录强制改密流程**
---
### Story 4经纪人找回用户名已废弃
> **状态**已废弃。普通员工用户名固定为手机号无需找回Tenant Admin 如忘记用户名请联系平台运营线下处理。本 Story 保留占位以维持版本记录,实现时跳过。
---
### Story 5手机验证码登录MVP 实现)
**As** 已有账号的经纪人,**I want** 通过手机号 + 短信验证码直接登录,**So that** 在忘记密码或不想输入密码时,仍能快速进入系统。
> **说明**:短信能力在 Story 3 找回密码中已建设完成,本 Story 复用。登录页提供「密码登录」和「验证码登录」两个并列 Tab用户自由切换两种方式均为 MVP 正式功能。
**验收标准**
- [ ] 登录页提供两种登录方式的切换 Tab**「密码登录」**(默认选中)和 **「验证码登录」**
- [ ] 切换 Tab 时,输入区域平滑切换,已填内容清空,滑块验证状态重置
**「验证码登录」界面元素**
- [ ] 手机号输入框(规格同 Story 211 位数字)
- [ ] 验证码输入框6 位数字分格输入)+ 「获取验证码」按钮60 秒倒计时冷却态)
- [ ] 滑块拼图验证区域(规格同 Story 2**先通过滑块验证,再允许点击「获取验证码」**
- [ ] 「登录」按钮(手机号 + 验证码均填写后方可点击)
**获取验证码逻辑**
- [ ] 用户须先完成滑块验证,「获取验证码」按钮方可点击;未完成滑块时点击 → 提示「请先完成滑块验证」
- [ ] 手机号格式不合法 → 前端拦截,提示「请输入完整的 11 位手机号」
- [ ] 不论手机号是否注册,前端文案统一显示「如该手机号已注册,验证码将在 1 分钟内发送」(防止枚举攻击)
- [ ] 后台仅在手机号存在且账号处于可用状态时实际发送短信
- [ ] 同一手机号在一段时间窗口内的发送次数有上限(与找回密码独立计数,互不共享);超限后提示「发送次数过多,请稍后再试」
- [ ] 短信内容模板「【Fonrey 房睿】您的登录验证码为 {code}5 分钟内有效,请勿泄露。」
**登录校验逻辑**
- [ ] 校验结果:
- 正确且未过期 → 登录成功,后续行为与 Story 2 密码登录完全一致(含初始密码状态判断)
- 错误 → 提示「验证码有误,请重新输入」;连续错误达到上限 → 本次验证码作废,提示「验证码已失效,请重新获取」
- 已过期 → 提示「验证码已过期,请重新获取」
- [ ] **账号被锁定**(密码登录失败次数触发):验证码登录仍受账号锁定限制,锁定期间无法通过任何方式登录,提示与 Story 2 一致
> **设计说明**:账号锁定是账号维度的安全策略,不区分登录方式;否则锁定形同虚设。
- [ ] **账号已停用**:提示「账号已停用,请联系您的管理员」
---
### Story 6预留——微信扫码登录v2 实现)
**As** 绑定了微信账号的经纪人,**I want** 在登录页扫描微信二维码完成登录,**So that** 免去输入账号密码的步骤,提升登录体验。
**当前状态**
- 本期登录页 UI 入口以「即将开放」禁用态展示,**不提供任何可点击的实际功能**
- 后端服务端在 MVP 中**不开放微信相关接口**,相关端点仅占位规划,详见 Tech 文档 §5.4
- v2 实现时的业务前置要求:
- 微信账号必须先在「个人设置」中与系统账号完成绑定
- 二维码有效期 3 分钟,过期后前端自动刷新二维码
- 同一微信账号在同一租户内只能绑定一个系统账号
---
## 6. 业务规则与功能详细说明
### 6.1 客户端 Tenant 识别业务流程
```
客户端启动
├─ 本地有 Tenant Code 缓存?
│ │
│ YES ──→ 复核缓存 Tenant Code 是否仍有效
│ │
│ 有效 ──→ 直接进入登录页
│ │
│ 无效 ──→ 清除缓存,进入 Tenant 识别页
└─ NO ──→ 显示 Tenant 识别页
用户输入 Tenant Code → 发起验证
验证成功 ──→ 缓存 Tenant Code → 进入登录页
验证失败 ──→ 显示错误信息,保持识别页
```
#### Tenant 识别页规范
| 元素 | 规格 |
| ----------- | --------------------------------------- |
| 页面背景 | 品牌色渐变(与登录页保持一致的视觉风格) |
| Logo | Fonrey 产品 Logo居中显示 |
| 标题 | 「欢迎使用 Fonrey 房睿」 |
| 副标题 | 「请输入您公司的专属识别码以继续」 |
| Tenant Code 输入框 | 单行数字输入,固定 12 位,支持粘贴;非数字字符自动过滤,超出 12 位截断 |
| 输入框 Label | 「公司识别码Tenant Code」 |
| 确认按钮 | 主色调按钮,文字「确认」 |
| 错误提示 | 输入框下方红色文字,固定区域占位(不影响布局抖动) |
| 帮助文案 | 「不知道识别码请联系您公司的Tenant Admin租户管理员」 |
> Tenant 验证接口的具体路径、请求/响应 Schema、限流阈值与 Schema 隔离实现:见 `TECH_STACK/登录管理技术方案.md` §5.3.1 与 §三。
---
### 6.2 登录页设计规范
#### 6.2.1 页面布局
登录页顶部以 **Tab 切换** 区分两种登录方式「密码登录」默认选中Tab 下方的表单区随当前选中 Tab 动态切换;微信扫码作为独立的「其他登录」保持禁用。
```
┌─────────────────────────────────────────┐
│ [租户 Logo] [租户公司名称] │ ← 顶部品牌区Tenant 识别后回填)
│ │
│ ┌──────────────┬──────────────────┐ │
│ │ 密码登录 ✓ │ 验证码登录 │ │ ← 登录方式 Tab默认选中「密码登录」
│ └──────────────┴──────────────────┘ │
│ │
│ ── 密码登录 Tab默认展示─────────── │
│ ┌───────────────────────┐ │
│ │ 手机号 │ │
│ └───────────────────────┘ │
│ ┌───────────────────────┐ │
│ │ 密码 👁 │ │
│ └───────────────────────┘ │
│ ┌─────────────────────────────────┐ │
│ │ [背景图 + 拼图缺口] 🔄 │ │ ← 右上角刷新图标
│ │ [拼图碎片] ◀ 拖动滑块完成拼图 ▶│ │
│ └─────────────────────────────────┘ │
│ ┌───────────────────────┐ │
│ │ 登 录 │ │ ← 主 CTA橙色
│ └───────────────────────┘ │
│ 忘记密码 │ ← 文字链接(忘记用户名入口已废弃)
│ │
│ ── 验证码登录 Tab切换后展示──────── │
│ ┌───────────────────────┐ │
│ │ 手机号 │ │
│ └───────────────────────┘ │
│ ┌─────────────────────────────────┐ │
│ │ [拼图验证] ← 先完成验证,再获取 │ │ ← 验证码登录下滑块前置
│ └─────────────────────────────────┘ │
│ ┌──────────────────┐ ┌─────────────┐ │
│ │ 验证码6 位) │ │ 获取验证码 │ │ ← 通过滑块后按钮可点击60s 冷却
│ └──────────────────┘ └─────────────┘ │
│ ┌───────────────────────┐ │
│ │ 登 录 │ │
│ └───────────────────────┘ │
│ 忘记密码 │
│ │
│ ─────────────── 其他登录 ──────────────│
│ [微信扫码登录 - 即将开放] │ ← 禁用态,灰色
│ │
│ 切换公司 │ ← 底部,小字链接
└─────────────────────────────────────────┘
```
#### 6.2.2 安全机制(业务视角)
| 机制 | 业务规则 |
|------|------|
| 验证码类型 | 滑块拼图行为验证码:用户拖动碎片至缺口完成验证,无需输入字符 |
| 验证判定 | 综合位置精度与滑动轨迹特征判断是否为人类行为;具体容差与算法见 Tech 文档 |
| 背景图来源 | 预置图库随机抽取,缺口位置每次随机生成,防止固定模式被预测 |
| 验证失败处理 | 拼图区域抖动提示,自动刷新新背景图;**不计入账号密码错误次数** |
| 密码错误锁定 | 同一账号连续密码错误达到阈值后自动锁定,到期自动解锁;管理员可手动解锁 |
| 验证码刷新 | 登录失败后自动刷新拼图;用户亦可主动点击「刷新」图标 |
| 传输安全 | 所有登录相关请求强制 HTTPS不允许 HTTP 降级 |
| 会话有效期 | 默认按工作日单日使用场景设定;可由 Tenant Admin 在「系统设置」中调整 |
> 滑块容差像素值、密码错误次数阈值、锁定时长、Session 默认时长、密码哈希算法、登录失败计数存储位置等实现口径,统一由 `TECH_STACK/登录管理技术方案.md` §六、§七、§八 定义;本 PRD 不重复。
---
### 6.3 账号与员工实名绑定规范
#### 6.3.1 绑定原则
- 每个系统登录账号必须与「组织人事管理」模块中的一条**员工档案Staff**绑定
- 账号与员工是 **1:1 关系**,一个员工对应一个账号,一个账号只能绑定一个员工
- **不支持用户自行注册**,所有账号均由有权限的管理角色创建
#### 6.3.2 账号创建权限分层
系统内共有两类账号创建场景,权限和规则各不相同:
**① Tenant Admin 账号(每个租户的超级管理账号)**
| 项目 | 业务规则 |
| ---- | ------------------------------------------------------------ |
| 创建时机 | 平台运营在平台管理后台开通租户时,系统**自动**以该租户联系人手机号创建 Tenant Admin 账号,无需手动设置 |
| 用户名 | **固定为该租户联系人的手机号**11 位数字),全局唯一,创建后不可更改 |
| 初始密码 | 系统统一固定初始密码(由平台运营在系统配置中设定),与普通员工相同 |
| 首次登录 | 强制修改初始密码,不可跳过 |
| 权限范围 | 拥有该租户内最高权限,可管理员工账号、角色、系统设置等 |
| 数量限制 | 每个租户仅限 1 个 Tenant Admin 账号v2 可扩展为多管理员) |
| 数据来源 | 联系人手机号在开通租户时由平台运营录入,必填 |
**② 普通员工账号(经纪人、店长、行政等)**
| 项目 | 业务规则 |
|------|------|
| 创建时机 | Tenant Admin 在「组织人事管理 → 新增员工」时,系统自动为该员工创建登录账号 |
| 用户名 | **固定为该员工的手机号**11 位数字),同租户内唯一,创建后不可更改 |
| 初始密码 | 系统统一固定初始密码(与 Tenant Admin 共用同一配置) |
| 首次登录 | 强制修改初始密码,**不可跳过**(详见 §6.4 |
| 密码重置 | Tenant Admin 可在员工管理界面对任意员工账号执行「重置密码」,重置后恢复为固定初始密码,触发首次登录强制改密流程 |
| 账号禁用 | 员工离职或被停用时,对应账号自动禁用;禁用账号无法登录,历史操作记录保留 |
#### 6.3.3 账号字段语义(业务视角)
| 字段 | Tenant Admin | 普通员工 | 业务说明 |
|------|------|------|------|
| 用户名 | 联系人手机号 | 员工手机号 | 登录 ID创建后不可更改 |
| 密码 | 系统统一初始密码 | 系统统一初始密码 | 必须安全哈希存储;首次登录强制修改 |
| 手机号 | 必填,同时作为用户名 | 必填,同时作为用户名 | 用于密码登录与短信验证码登录;存储须加密 |
| 邮箱 | 选填 | 选填 | 在本系统无必须业务用途,完全可选 |
| 员工档案关联 | 可选关联 | 必须关联 | 实名绑定 |
| 账号状态 | active / disabled / locked | active / disabled / locked | locked 为密码错误锁定,到期自动恢复 |
| 初始密码标记 | 是 / 否 | 是 / 否 | 为"是"时登录成功后强制跳转改密页 |
| 创建人 | 平台运营 | Tenant Admin | 审计追溯 |
> 字段类型、字段名、表名、索引、跨 App 依赖、Migration 顺序等实现口径,全部以 `DATA_MODEL/DATA_MODEL_LOGIN.md` 为唯一权威。
---
### 6.4 首次登录强制修改密码
- 新员工账号创建后,账号处于「初始密码」状态
- 员工使用手机号 + 固定初始密码登录成功后,系统**立即跳转**至「首次登录强制改密页」,**不可关闭、不可跳过**,任何其他系统功能页面均不可访问
- Tenant Admin 对员工账号执行「重置密码」后,账号重新进入「初始密码」状态,该员工下次登录时再次触发强制改密流程
- 修改成功后,账号脱离「初始密码」状态,原 Session 保持有效,直接进入系统首页
**首次登录强制改密页规范**
| 元素 | 规格 |
|------|------|
| 页面标题 | 「欢迎使用 Fonrey请先设置您的登录密码」 |
| 提示文案 | 「您当前使用的是初始密码,为保障账号安全,请立即设置新密码后开始使用」 |
| 新密码输入框 | 密文显示,右侧「显示/隐藏」切换 |
| 确认新密码输入框 | 密文显示,与新密码一致性实时校验 |
| 密码强度提示 | 逐条实时显示规则达标状态(✓/✗):长度 ≥ 8 位 / 包含字母 / 包含数字 |
| 提交按钮 | 「确认并进入系统」 |
| 不可操作项 | 无「跳过」按钮;顶部导航栏、侧边菜单、关闭按钮均禁用 |
> 历史密码校验范围、密码强度算法等实现细节见 Tech 文档与 `DATA_MODEL_LOGIN.md` 中历史密码记录表设计。
---
### 6.5 找回密码业务流程
> 实现细节(一次性凭证 TTL、OTP 有效期、错误次数阈值、限流计数策略)见 `TECH_STACK/登录管理技术方案.md` §6.3 与 §七。
```
用户点击「忘记密码」
步骤1输入手机号
├─ 输入 11 位手机号,点击「获取验证码」
│ │
│ 前端文案统一为「如该手机号已注册,验证码将在 1 分钟内发送」(防止枚举)
│ │
│ 后台:手机号存在且账号可用 → 生成 OTP → 发送短信
│ 不存在或已停用 → 静默处理
步骤2输入短信验证码
├─ 输入 6 位验证码,点击「下一步」
│ │
│ 正确且未过期 → 颁发一次性凭证 → 进入步骤3
│ 错误(次数未到上限)→ 提示「验证码有误,请重新输入」
│ 错误(达到上限)→ 提示「验证已失败,请重新获取验证码」,本次 OTP 作废
│ 已过期 → 提示「验证码已过期,请重新获取」
步骤3重置密码
├─ 服务端校验一次性凭证有效性
│ │
│ 无效/过期 → 提示「操作已超时请重新发起找回密码」跳回步骤1
├─ 用户输入新密码 + 确认新密码,实时逐条校验复杂度规则(✓/✗)
└─ 提交成功
→ 更新密码,账号脱离「初始密码」状态
→ 清除该账号所有有效 Session强制重新登录
→ 跳转登录页,提示「密码已重置,请使用新密码登录」
```
---
### 6.6 手机验证码登录(业务规则补充)
> 本节为 Story 5 的业务规则补充。短信能力在 Story 3 找回密码中已建设完成,本节描述在**登录场景**下复用时的关键业务差异点。
**与找回密码短信逻辑的业务差异对比**
| 维度 | 找回密码Story 3 | 验证码登录Story 5 |
|------|-------------------|---------------------|
| 业务场景 | 密码重置 | 登录认证 |
| OTP 有效期 | 较长 | 较短 |
| 每小时发送上限 | 较低 | 较高 |
| 验证成功后动作 | 颁发一次性凭证 → 步骤三重置密码 | 直接登录成功 |
| 短信文案 | 「密码重置验证码」 | 「登录验证码」 |
| 账号锁定影响 | 不受密码错误锁定限制(非密码登录路径) | **受账号锁定限制**(账号维度安全策略,不区分方式)|
> 各项数值OTP 时长、每小时上限)口径见 `TECH_STACK/登录管理技术方案.md` §6.3、§6.4、§七。
**滑块验证前置规则**(验证码登录特有):
- 用户须先完成滑块拼图验证,「获取验证码」按钮方可点击
- 滑块验证通过后,拼图区域保持「验证通过」状态,不需要在点击「登录」前再次验证
- 切换 Tab 时,滑块验证状态重置(须重新完成验证后方可获取验证码)
**短信记录复用说明**
- 不新建表,复用 `DATA_MODEL_LOGIN.md` 中定义的短信验证码记录表
- 通过场景字段区分"登录"与"密码重置",各自独立限流计数
- 同一手机号同一场景同一时间只有一条有效 OTP新发送时将旧记录置为失效
---
### 6.7 后端数据模型
> 数据模型已迁移至独立文档,请参阅:**`DATA_MODEL/DATA_MODEL_LOGIN.md`**
该文档包含:
- 账号主表(完整字段定义、约束、索引)
- 登录审计表
- 短信验证码记录表(找回密码 + 验证码登录共用)
- 历史密码记录表
- Redis 缓存结构说明
- 账号状态机与创建流程
-`org.Staff` 的关联规则及跨 App 依赖设计
- Migrations 迁移顺序说明
- 架构决策说明ADR
---
### 6.8 Electron 客户端约定
> Electron 客户端在登录链路上的实现约定Tenant Code 加密存储、Session Cookie 策略、登录页加载、多标签页、登出、窗口关闭、强制更新、安全约束)已迁移至 `TECH_STACK/登录管理技术方案.md` §十三 Electron 客户端约定。
本 PRD 仅约束业务行为:
- 客户端必须在登录前完成 Tenant 识别,且 Tenant Code 须**加密**持久化
- 客户端登出后,本地不得保留可直接复用的登录凭证
- 客户端版本低于服务端要求的最低版本时,**必须阻断登录流程**并展示更新提示(联动平台管理后台 PRD 的客户端发布章节)
- 同一客户端窗口内的多标签页应共享同一登录态
---
## 7. 技术注意事项(产品视角)
### 7.1 业务依赖
- 短信发送依赖具备短信资质的服务商;签名与模板审核须在功能上线前完成
- 短信发送须异步处理,避免阻塞登录链路;密码登录可作为短信故障时的保底入口
- 多租户隔离与跨 Schema 调用细节由 `TECH_STACK/登录管理技术方案.md``DATA_MODEL/DATA_MODEL_LOGIN.md` 定义
### 7.2 已知风险
| 风险 | 可能性 | 影响 | 缓解措施 |
|------|--------|------|---------|
| 滑块验证被机器模拟轨迹绕过 | 低 | 高 | 服务端综合位置 + 轨迹特征校验;后续可引入设备指纹加固 |
| Tenant Code 枚举攻击(暴力试探) | 低 | 中 | 接口限流 + 统一外显文案,不区分「未找到」与「已禁用」 |
| 密码重置凭证泄露 | 低 | 高 | 一次性、短时效、HTTPS 传输 |
| 短信服务故障 | 中 | 高 | 失败告警 + 密码登录保底 + 建议配置备用短信通道 |
| 多端同时登录同一账号 | 高(日常场景) | 低 | 本期允许,后续如需踢出再做版本号机制 |
### 7.3 开放问题(开发前需确认)
- [ ] **短信服务商选型**:阿里云 / 腾讯云 / 其他?短信签名与模板审核需要 13 个工作日 — 负责人:后端负责人 — 截止:开发启动前
- [ ] **Session 默认有效期**8 小时是否满足各租户需求?是否允许 Tenant Admin 自行配置?— 负责人:产品经理 — 截止:开发启动前
- [ ] **滑块拼图实现方案**:自研还是集成第三方行为验证服务?需评估数据合规要求 — 负责人:后端负责人 + 安全 — 截止:开发启动前
- [ ] **账号锁定通知**:账号被锁定后,是否自动发短信通知用户和/或通知管理员?— 负责人:产品经理 — 截止:开发启动前
- [ ] **历史密码校验范围**:最近 3 次是否足够?是否需要额外规则(如不能与用户名相同)?— 负责人:产品经理 — 截止:开发启动前
---
## 8. 发布计划
| 阶段 | 时间 | 受众 | 准入门槛 |
|------|------|------|---------|
| 内部 Alpha | 待定 | 研发团队 + 1 家种子租户 | 核心流程Tenant 识别 + 账密登录 + 找回密码)无 P0 Bug |
| 封闭 Beta | 待定 | 5 ~ 10 家测试租户 | 登录成功率 ≥ 99%,验证码拦截机制正常运作 |
| 正式发布 | 待定 | 全量租户 | Beta 阶段无未修复的安全漏洞;帮助文档发布 |
**回滚标准**:若正式发布后 24 小时内登录失败率(非验证码拦截原因)超过 2%,或出现账号数据泄露事件,立即回滚并启动安全审查。
---
## 9. 附录
### 9.1 登录状态流转图
```
[未识别 Tenant]
│ 输入有效 Tenant Code
[未登录]
│ 账密 / 验证码登录成功
[初始密码状态](如账号为初始密码)
│ 强制改密成功
[已登录 - Active Session]
│ Session 过期 / 主动登出 / 管理员强制登出
[未登录](跳转登录页)
[账号锁定状态](密码连续错误达到阈值后)
│ 锁定时长结束自动解锁 或 管理员手动解锁
[未登录](可重新登录)
```
### 9.2 业务能力清单(替代原"接口清单"
> 本文件不再列出具体接口路径与 HTTP 方法。完整 API 端点清单含路径、方法、Schema 位置、是否鉴权、预留端点)请查阅 `TECH_STACK/登录管理技术方案.md` §五。
| 业务能力 | 提供给谁 | 说明 |
|---|---|---|
| Tenant 识别 | 客户端 | 输入 12 位 Tenant Code返回租户品牌与登录入口 |
| 获取/校验滑块验证码 | 登录页 | 行为验证码生成与校验,输出一次性通过凭证 |
| 密码登录 | 已识别租户的用户 | 手机号 + 密码 + 滑块凭证完成认证 |
| 验证码登录 | 已识别租户的用户 | 手机号 + 短信验证码完成认证(需先通过滑块再获取验证码) |
| 登出 | 已登录用户 | 销毁服务端会话与本地登录凭证 |
| 找回密码(三步) | 忘记密码的用户 | 发送 OTP → 校验 OTP → 设置新密码 |
| 首次登录强制改密 | 处于初始密码状态的用户 | 强制流程,提交后脱离初始密码状态 |
| 微信扫码登录v2 预留) | 全量用户 | MVP 仅展示禁用入口v2 实现 |
### 9.3 相关文档参考
- 技术栈总纲:`TECH_STACK/TECH_STACK.md`
- **登录管理技术方案(实现口径权威)**`TECH_STACK/登录管理技术方案.md`
- **登录管理数据模型(数据口径权威)**`DATA_MODEL/DATA_MODEL_LOGIN.md`
- 全局 API 契约:`TECH_STACK/API_CONTRACT.md`
- ADR`ADR.md`(特别是 `ADR-20260502-003` PRD/Tech 职责边界、`ADR-20260430-004` 登录接口路径同步规则)