简介
本设计文档聚焦 DouPHP 用户系统的核心数据模型,围绕“用户基本信息表(user)”的字段设计与业务语义展开,覆盖注册信息、登录凭证、安全验证、状态管理、账户激活、密码重置、行为追踪与安全日志、访问控制等关键能力。同时给出与等级、联系人、标签、钱包快照等扩展表的关联关系,以及认证授权与会话管理的表结构设计建议,面向用户系统开发者与安全工程师提供完整参考。
项目结构
- 用户主表 user 由前台与后台共用,分别通过 front/model/user/User.php 与 admin/model/user/User.php 声明可写字段与类型转换。
- 安全与审计相关:user_log 记录用户操作日志;升级脚本中统一了时间字段命名并建立索引。
- 等级体系:user_level 定义会员等级,user.level_id 关联至该表。
- 联系人与标签:user_contact 存储联系人信息;user_tag 用于运营分群。
- 钱包快照:user_wallet 作为余额与积分的冷读快照,权威流水在 dou_money / dou_user_point。
- 第三方登录:user_sns 记录社交账号绑定信息,API 层在注册时写入 user 与 user_sns。
graph TB
subgraph "用户域"
U["user(用户主表)"]
UL["user_level(等级)"]
UC["user_contact(联系人)"]
UT["user_tag(标签)"]
UW["user_wallet(钱包快照)"]
USNS["user_sns(社交绑定)"]
ULG["user_log(操作日志)"]
end
U --> UL
U --> UC
U --> UT
U --> UW
U --> USNS
U --> ULG
核心组件
- 用户主表 user:承载注册信息、登录凭证、安全校验与状态字段。关键字段包括:
- 标识与基础信息:id、user_sn、nickname、sex、avatar、defined
- 联系方式:mobile、email
- 安全凭证:password、token、token_expires_at、reset_token、reset_token_expires_at
- 安全策略:login_count、login_fail_count、login_locked_at
- 状态与时间:status、created_at
- 等级表 user_level:name、upgrade_type、upgrade_condition、good_discount、icon 等,供用户等级与权益使用。
- 联系人表 user_contact:name、phone、id_card、province/city/district、address、tag、is_default、sort、created_at。
- 标签表 user_tag:user_id、tag,支持按用户或标签过滤。
- 钱包快照 user_wallet:money/point 余额与累计统计聚合视图,主键为 user_id。
- 操作日志 user_log:记录用户操作结果与时间,便于审计与风控。
架构总览
下图展示用户域内核心表之间的关系,以及 API 注册流程对 user 与 user_sns 的写入路径。
sequenceDiagram
participant Client as "客户端"
participant API as "API 控制器"
participant DB as "数据库"
participant SNS as "user_sns"
participant User as "user"
Client->>API : "提交注册/绑定手机号/邮箱"
API->>DB : "插入 user(user_sn,mobile,email,password,nickname,..." )
DB-->>API : "返回新ID"
API->>SNS : "插入社交绑定(openid,unionid,apptype)"
API->>DB : "更新 user.login_count +1"
API-->>Client : "返回注册成功"
详细组件分析
用户主表 user:字段设计与业务语义
- 身份与基础信息
- id:主键
- user_sn:用户编号,便于对外唯一标识
- nickname、sex、avatar、defined:昵称、性别、头像、自定义扩展
- 联系方式
- mobile、email:手机号与邮箱,用于登录、通知与找回
- 安全凭证与令牌
- password:密码哈希
- token、token_expires_at:会话/记住我令牌及过期时间
- reset_token、reset_token_expires_at:找回密码独立令牌及过期时间
- 安全策略与风控
- login_count:登录次数
- login_fail_count:失败计数,配合锁定机制
- login_locked_at:锁定时间,达到阈值后临时锁定
- 状态与时间
- status:账户状态(如 active/suspended/deactivated),用于启用、暂停、注销等生命周期管理
- created_at:创建时间(已统一为 DATETIME)
说明
- 字段白名单与类型转换由前后端 Model 共同约束,避免越权写入。
- 升级脚本确保密码长度、时间字段命名一致,并补齐缺失字段。
classDiagram
class User {
+int id
+string user_sn
+string nickname
+bool sex
+string avatar
+string defined
+string mobile
+string email
+string password
+string token
+datetime token_expires_at
+string reset_token
+datetime reset_token_expires_at
+int login_count
+tinyint login_fail_count
+datetime login_locked_at
+string status
+datetime created_at
}
账户状态管理与生命周期
- 状态字段 status 用于表达账户当前生命周期阶段,常见取值包括:
- active:正常可用
- suspended:暂停(限制登录或部分功能)
- deactivated:注销(不可恢复或需二次确认)
- 结合 login_locked_at 实现短时锁定,防止暴力破解;当达到失败阈值后设置锁定时间,并在解锁前拒绝登录。
- 注册成功后默认状态应为 active;管理员可在后台调整状态以进行风控或运营干预。
flowchart TD
Start(["登录请求"]) --> CheckLock{"是否处于锁定?"}
CheckLock --> |是| Deny["拒绝登录并提示"]
CheckLock --> |否| Verify["校验用户名/密码"]
Verify --> Ok{"校验成功?"}
Ok --> |否| IncFail["失败计数+1<br/>必要时设置锁定时间"]
IncFail --> Deny
Ok --> |是| UpdateLogin["登录次数+1<br/>清理失败计数/锁定"]
UpdateLogin --> Allow["允许登录"]
密码重置流程的数据模型
- 独立令牌:reset_token 与 reset_token_expires_at 用于密码重置链接的短期有效性控制。
- 流程要点:
- 生成随机 reset_token,写入 user 表并设置过期时间
- 发送重置邮件/短信,包含带 token 的重置链接
- 校验 token 有效且未过期后,允许设置新密码并清空 reset_token
- 安全建议:
- 每次重置均刷新 token 与过期时间
- 重置成功后立即失效旧 token,防止重放攻击
sequenceDiagram
participant U as "用户"
participant S as "服务"
participant DB as "数据库"
U->>S : "请求重置密码"
S->>DB : "生成 reset_token 并设置过期时间"
S-->>U : "发送重置链接"
U->>S : "携带 reset_token 提交新密码"
S->>DB : "校验 token 存在且未过期"
DB-->>S : "通过"
S->>DB : "更新密码并清空 reset_token"
S-->>U : "重置成功"
用户等级与权益
- user_level 表维护等级名称、升级条件、折扣等配置。
- user.level_id 指向具体等级,便于列表预加载与权限计算。
- 可通过 Config 开关与 exists 检查决定是否启用等级模块,提升兼容性。
classDiagram
class UserLevel {
+int id
+string name
+string upgrade_type
+string upgrade_condition
+decimal good_discount
+string icon
+datetime created_at
}
class User {
+int level_id
}
User --> UserLevel : "level_id 关联"
联系人、标签与钱包快照
- 联系人 user_contact:支持多地址/电话、默认标记、排序与地区信息,便于订单与预约场景。
- 标签 user_tag:一用户多标签,支持按用户或标签筛选,用于运营分群与精准营销。
- 钱包快照 user_wallet:提供 money/point 余额与累计统计的快速读取,权威流水仍来自 dou_money / dou_user_point。
erDiagram
USER ||--o{ USER_CONTACT : "拥有多个联系人"
USER ||--o{ USER_TAG : "拥有多个标签"
USER ||--|| USER_WALLET : "一对一快照"
行为追踪与安全日志
- user_log 记录用户操作结果与时间,便于审计、排障与风控。
- 升级脚本将 create_time 统一迁移为 created_at,并建立索引以提升查询性能。
classDiagram
class UserLog {
+int id
+int user_id
+int result
+datetime created_at
}
第三方登录与社交绑定
- 注册流程会同时写入 user 与 user_sns,并递增 login_count。
- user_sns 包含 openid、unionid、apptype 等字段,用于跨平台识别与合并。
sequenceDiagram
participant C as "客户端"
participant W as "微信控制器"
participant DB as "数据库"
C->>W : "提交注册/绑定参数"
W->>DB : "INSERT INTO user(...)"
W->>DB : "INSERT INTO user_sns(...)"
W->>DB : "UPDATE user SET login_count = login_count + 1"
W-->>C : "返回成功"
依赖关系分析
- user 与 user_level:一对多(一个等级对应多个用户),通过 level_id 关联。
- user 与 user_contact:一对多,支持默认联系人标记。
- user 与 user_tag:一对多,用于运营分群。
- user 与 user_wallet:一对一,提供快速读取的余额与积分快照。
- user 与 user_log:一对多,记录用户行为与结果。
- user 与 user_sns:一对多,记录第三方平台绑定。
graph LR
U["user"] --> L["user_level"]
U --> C["user_contact"]
U --> T["user_tag"]
U --> W["user_wallet"]
U --> LG["user_log"]
U --> S["user_sns"]
性能考虑
- 时间字段统一为 created_at,并建立索引,利于日志与列表查询。
- 列表读取时可按需预加载 user_level,减少 N+1 查询。
- 钱包快照 user_wallet 提供冷读优化,避免频繁聚合流水表。
- 登录失败计数与锁定字段应配合缓存或限流中间件,降低数据库压力。
故障排查指南
- 登录失败与锁定
- 检查 login_fail_count 与 login_locked_at,确认是否触发锁定策略。
- 若锁定时间异常,核对升级脚本与时间字段迁移是否正确。
- 密码重置无效
- 检查 reset_token 是否存在且未过期,确认重置成功后是否清空 token。
- 注册后未递增登录次数
- 核对注册流程是否执行 login_count +1 的更新逻辑。
- 日志查询缓慢
- 确认 user_log.created_at 已建立索引,避免全表扫描。
结论
DouPHP 用户系统以 user 为核心,围绕安全凭证、状态管理、风控策略与审计日志构建了完整的用户数据模型。通过等级、联系人、标签与钱包快照等扩展表,满足多样化业务需求。升级脚本确保了字段一致性与性能优化。建议在认证授权与会话管理中严格遵循令牌有效期与最小权限原则,并结合日志与风控策略保障系统安全。
附录
- 推荐索引
- user.email、user.mobile:唯一或普通索引,加速登录与查找
- user.status:普通索引,便于状态筛选
- user_log.user_id、user_log.created_at:复合索引,优化按用户与时间的查询
- user_sns.user_id、user_sns.openid:普通索引,加速绑定查询
- 安全建议
- 密码必须使用强哈希算法存储
- token/reset_token 必须设置短过期时间并一次性使用
- 登录失败阈值与锁定时间应可配置,并支持管理员手动解锁
- 敏感字段(如身份证、支付码)应加密存储并限制访问