Files
nexus/Project/fonrey/TECH_STACK/登录管理技术方案.md
2026-04-30 18:40:55 +08:00

9.0 KiB
Raw Blame History

For AI assistants: Read this entire file before writing any code. All decisions here are final. Do not suggest alternatives unless asked.

Fonrey 登录管理技术方案

版本: 4.0
项目: Fonrey 房产经纪管理系统
技术栈: Django 4.x + HTMX + Alpine.js + PostgreSQL 16 + Redis + Celery
关联 PRD: PRD/登录管理/用户登录管理模块PRD.mdv2.0
关联数据模型: DATA_MODEL/DATA_MODEL_LOGIN.md(本方案不重复 DDL
关联契约规范: TECH_STACK/API_CONTRACT.md(全局 API 契约权威)
关联测试规范: TECH_STACK/测试规范.mdTEST_CASES/TEST_CASES_LOGIN_MODULE.md
最后更新: 2026-04-30


一、文档定位与边界

本文件定义登录模块的实现口径:

  1. 模块范围与职责边界
  2. API 端点(页面 / HTMX / JSON
  3. 安全策略(滑块验证、登录锁定、短信 OTP、会话
  4. Redis/Celery 运行策略
  5. 错误码与测试映射

本文件不展开数据表字段与索引。数据结构以 DATA_MODEL_LOGIN.md 为唯一权威。


二、范围定义(以 PRD v2.0 为准)

2.1 P0 必须覆盖

  • Tenant Code 识别(首次启动 + 切换公司)
  • 密码登录(手机号/密码 + 滑块)
  • 首次登录强制修改密码
  • 找回密码(纯短信三步流程)
  • 手机验证码登录MVP 正式功能)
  • 登录失败锁定 / 自动解锁 / 管理员解锁
  • 安全登出与会话失效

2.2 非目标 / 预留

  • 微信扫码登录(仅保留禁用入口与接口占位,不开放功能)
  • 企业 SSOOAuth2 / SAML
  • 风险评分/设备指纹

2.3 已废弃(不得实现)

  • 找回用户名流程Story 4 已废弃)

三、模块架构边界

3.1 模块职责(apps/account

  • 租户识别与租户上下文建立前置校验
  • 登录鉴权、会话签发、登出销毁
  • 首登改密门禁(is_initial_password
  • 短信 OTP 发送/校验(找回密码 + 验证码登录)
  • 登录与安全审计事件写入

3.2 多租户分层职责

层级 Schema 职责
Tenant Code 校验 Public 校验 tenant_code、租户状态、品牌信息返回
登录认证 Tenant 账号鉴权、失败计数、锁定状态、会话签发
短信 OTP Tenant OTP 记录、场景区分、过期与尝试次数控制

3.3 外部依赖

依赖模块 用途
apps/org 员工状态联动(离职/停用不可登录)
core/encryption.py 手机号加密/哈希能力
core/cache.py 滑块票据、频控、锁定计数、重置 token
Celery 短信发送异步化(可选,建议)

四、API 设计原则

  1. 登录安全链路:Tenant 校验 → 滑块验证 → 登录提交
  2. 防枚举:账号不存在/停用等敏感状态采用统一外显文案。
  3. 账号锁定是账号维度策略,不区分密码登录或验证码登录。
  4. Redis 仅作运行态与频控,最终状态以数据库持久化字段为准。
  5. 所有登录相关接口遵循 TECH_STACK/API_CONTRACT.md 的统一错误响应格式。

五、端点清单(对齐 PRD

5.1 页面路由SSR

路径 方法 鉴权 说明
/auth/tenant/identify/ GET Tenant 识别页
/auth/login/ GET 登录页(密码登录/验证码登录 Tab
/auth/password/forgot/ GET 找回密码三步页
/auth/password/change-initial/ GET 首次登录强制改密页

说明:/auth/wechat/* 仅预留,不在 MVP 开放。

5.2 HTMX 片段端点

路径 方法 用途 返回
/auth/fragments/captcha/ GET 刷新滑块区块 HTML 片段
/auth/fragments/login-form/ GET 登录 Tab 内容局刷 HTML 片段
/auth/fragments/forgot-step/ GET 找回密码步骤局刷 HTML 片段

5.3 JSON APIMVP

端点 方法 说明
/api/auth/tenant/verify/ POST Tenant Code 校验(公开接口)
/api/auth/captcha/ GET 获取滑块拼图验证码(返回背景图 Base64 + 碎片图 Base64 + 验证 Token
/api/auth/captcha/verify/ POST 校验滑块并签发 captcha_pass_token
/api/auth/login/ POST 密码登录
/api/auth/login/phone/ POST 手机验证码登录
/api/auth/recover/password/request/ POST 找回密码步骤一:发 OTP
/api/auth/recover/password/verify/ POST 找回密码步骤二:校验 OTP颁发 sms_reset_token
/api/auth/recover/password/reset/ POST 找回密码步骤三:提交新密码
/api/auth/password/change-initial/ POST 首次登录强制改密提交
/api/auth/logout/ POST 登出销毁会话

六、关键流程约束

6.1 Tenant 识别

  • tenant_code 固定 12 位数字,前后空格自动 trim
  • 成功返回租户名称、Logo URL、登录地址
  • 失败返回:valid=false + 统一错误信息
  • 接口公开但必须限流:单 IP 每分钟 ≤ 10 次

6.2 密码登录

请求体(示例):

{
  "phone": "13800138000",
  "password": "***",
  "captcha_pass_token": "token"
}

关键规则:

  • 滑块通过后方可提交登录
  • 密码连续错误 ≥ 5 次,锁定 30 分钟
  • is_initial_password = true 时强制跳转改密页
  • 错误文案统一,不泄露账号存在性细节

6.3 找回密码(纯短信三步)

步骤一:发送 OTP

  • scene = password_reset
  • OTP 有效期10 分钟
  • 同手机号频控5 次/小时
  • 手机号不存在/停用:统一提示“如该手机号已注册,验证码将在 1 分钟内发送”

步骤二:校验 OTP

  • 正确且未过期:签发 sms_reset_token15 分钟,一次性)
  • 错误累计尝试≥5 次作废该 OTP
  • 过期:提示重新获取

步骤三:重置密码

  • 必须携带有效 sms_reset_token
  • 成功后:is_initial_password = false
  • 该用户所有会话立即失效,跳回登录页

6.4 手机验证码登录MVP 正式)

请求体(示例):

{
  "phone": "13800138000",
  "sms_code": "123456"
}

关键规则:

  • 获取登录验证码前必须先通过滑块
  • scene = login
  • OTP 有效期5 分钟
  • 同手机号频控10 次/小时(与 password_reset 独立计数)
  • OTP 错误 ≥5 次作废
  • 账号 lockeddisabled 时,验证码登录同样拒绝

七、Redis Key 规范(对齐 PRD

Key TTL 说明
captcha_token:{uuid} 3 分钟 滑块验证会话
captcha_pass:{uuid} 3 分钟 一次性通过凭证
login_fail:{tenant_id}:{username} 30 分钟 登录失败计数
sms_limit:password_reset:{phone} 1 小时 找回密码 OTP 发送频控≤5次
sms_limit:login:{phone} 1 小时 登录 OTP 发送频控≤10次
sms_reset_token:{token} 15 分钟 找回密码步骤三凭证
tenant_verify_ip:{ip} 1 分钟 Tenant 校验接口 IP 限流≤10次

八、安全与合规

  1. 密码仅允许 Django 安全哈希PBKDF2/Argon2
  2. OTP 明文不得入库,仅存哈希。
  3. 敏感字段日志脱敏手机号、token、验证码
  4. 会话过期或登出后,受保护页面必须重定向登录。
  5. HTTPS 强制,不允许明文传输降级。

九、错误码建议(登录模块)

code HTTP 中文含义
AUTH_TENANT_NOT_FOUND 400 租户识别码无效
AUTH_TENANT_RATE_LIMITED 429 Tenant 校验请求过于频繁
AUTH_CAPTCHA_INVALID 400 滑块验证失败
AUTH_INVALID_CREDENTIAL 401 手机号或密码错误
AUTH_ACCOUNT_LOCKED 423 账号已锁定
AUTH_ACCOUNT_DISABLED 403 账号已停用
AUTH_SMS_OTP_INVALID 400 短信验证码错误
AUTH_SMS_OTP_EXPIRED 400 短信验证码过期
AUTH_SMS_OTP_RATE_LIMITED 429 OTP 发送超限
AUTH_SMS_RESET_TOKEN_INVALID 400 重置凭证无效或过期
AUTH_PASSWORD_WEAK 400 新密码不满足强度规则

十、测试映射(与全局编号对齐)

  • 测试编号规范:TEST_CASES/TEST_CASE_ID_SPEC.md
  • 注册表:TEST_CASES/TEST_CASE_REGISTRY.md
  • 登录模块用例:TEST_CASES/TEST_CASES_LOGIN_MODULE.md

建议最小执行集:

  • Tenant 识别:TC-FON-000001 ~ 000010
  • 密码登录与锁定:TC-FON-000011 ~ 000028
  • 首登改密:TC-FON-000029 ~ 000033
  • 找回密码:TC-FON-000034 ~ 000044
  • 验证码登录:TC-FON-000045 ~ 000048

十一、落地顺序建议

  1. Tenant 识别 + 密码登录主链路
  2. 滑块与失败锁定
  3. 首登改密门禁
  4. 找回密码三步(短信)
  5. 手机验证码登录scene=login
  6. 报表与监控补齐

十二、文档同步规则

  • PRD 登录模块变更:同步本文件
  • 数据结构调整:同步 DATA_MODEL_LOGIN.md
  • 测试用例新增/变更:同步 TEST_CASES/TEST_CASE_REGISTRY.md 与登录用例文档
  • API 契约调整:同步 TECH_STACK/API_CONTRACT.md