文档目录
用户服务实现

简介

本文件面向 DouPHP 框架的用户服务实现,聚焦以下业务与安全能力:

  • 用户注册、登录(账号密码、手机验证码)、第三方社交账号绑定/解绑
  • 权限与状态管理(封禁/解禁/注销、登录态校验)
  • 会员等级、积分系统、余额与优惠券统计、收藏数等
  • 用户行为审计与追踪(登录成功/失败、IP 限流、账户锁定)
  • 与其他模块的协作模式(订单、营销、内容等通过配置开关与查询聚合)

文档以“分层职责 + 数据流 + 安全策略”为主线,配合时序图、流程图与类图帮助读者快速理解并扩展。

项目结构

用户相关代码主要分布在三层:

  • 前台服务层 front/service/user:面向前端交互的业务编排(登录、注册、资料、导航等)
  • 核心服务层 core/service/user:通用认证、等级、统计、推广、联系人等能力
  • 后台服务层 admin/service/user:后台用户管理、列表、批量操作、Excel 导出、手工等级调整
graph TB
subgraph "前台服务"
F_Login["LoginService"]
F_Reg["RegistrationService"]
end
subgraph "核心服务"
C_UserSvc["UserService"]
C_Auth["UserAuthService"]
C_Level["UserLevelService"]
C_Stats["UserStatsService"]
end
subgraph "后台服务"
A_UserSvc["UserService(后台)"]
end
F_Login --> C_Auth
F_Reg --> C_UserSvc
A_UserSvc --> C_Stats
A_UserSvc --> C_UserSvc
C_Level --> C_Stats

核心组件

  • 登录服务(前台):负责凭据校验、IP 限流、账户锁定检查、历史 md5 升级 bcrypt、审计日志记录;不写会话/Token,由调用方完成登录态写入。
  • 注册服务(前台):协议单页保障、API 验证码 token 生成、注册数据组装、事务化创建用户、SNS 绑定/解绑。
  • 用户核心服务(核心):资料读模型、扩展身份(VIP/工作端/分销)、收货联系人、推广关系解析与登记、随机编号/头像名生成。
  • 认证服务(核心):会话/Token 签发、记住我、登录失败计数与锁定、IP 限流、登录态校验。
  • 等级服务(核心):自动升级判定、成长进度计算、升级日志记录。
  • 统计服务(核心):积分、余额、优惠券可用数、收藏数、累计消费、累计推广收益及批量聚合。
  • 后台用户服务(后台):用户列表、编辑/新增/删除、批量操作、Excel 导出、手工等级调整日志。

架构总览

用户服务采用“前台编排 + 核心能力 + 后台管理”的分层设计:

  • 前台服务专注交互流程与参数校验,委托核心服务完成跨端复用的认证、等级、统计等逻辑
  • 核心服务提供稳定签名与可插拔能力(按 features 开关控制功能可用性)
  • 后台服务复用核心能力,叠加管理视图所需的数据拼装与审计日志
sequenceDiagram
participant Client as "客户端"
participant Front as "前台控制器"
participant LoginSvc as "LoginService"
participant AuthSvc as "UserAuthService"
participant DB as "数据库"
Client->>Front : 提交登录表单
Front->>LoginSvc : validateLoginCredentials(账号, 密码, IP)
LoginSvc->>AuthSvc : ipRateLimit(IP)
alt 达到限流阈值
LoginSvc-->>Front : 返回错误(IP被限制)
else 未限流
LoginSvc->>DB : 根据邮箱/手机号查用户
LoginSvc->>AuthSvc : isLocked(userId)
alt 账户锁定
LoginSvc-->>Front : 返回错误(账户锁定)
else 未锁定
LoginSvc->>DB : 校验密码(md5/bcrypt)
alt 密码错误
LoginSvc->>AuthSvc : loginFail(userId)
LoginSvc-->>Front : 返回错误(密码错误)
else 密码正确
LoginSvc->>AuthSvc : loginSuccess(userId)
LoginSvc-->>Front : 返回user行
Front->>AuthSvc : 写会话或签发API Token
Front-->>Client : 登录成功响应
end
end
end

详细组件分析

登录服务(前台)

  • 职责边界:仅做凭据校验与审计,不写会话/Token;支持账号密码与手机验证码两种路径
  • 安全要点:
    • IP 限流:基于 user_log 在窗口期内失败次数判断
    • 账户锁定:login_locked_at 截止时间未到则拒绝登录
    • 密码兼容:历史 md5 命中后自动升级为 bcrypt
    • 状态检查:status 为已注销/停用时拒绝登录
  • 审计:登录成功/失败均写 user_log,附带 detailTag
flowchart TD
Start(["进入 validateLoginCredentials"]) --> CheckIP["IP 限流检查"]
CheckIP --> |超限| ReturnIP["返回IP受限错误"]
CheckIP --> |未超限| FindUser["按邮箱/手机号查找用户"]
FindUser --> Locked{"是否锁定?"}
Locked --> |是| ReturnLock["返回账户锁定错误"]
Locked --> |否| VerifyPwd["校验密码(md5/bcrypt)"]
VerifyPwd --> PwdOk{"密码正确?"}
PwdOk --> |否| FailCount["累加失败次数并记录审计"] --> ReturnPwd["返回密码错误"]
PwdOk --> |是| StatusCheck["检查用户状态"]
StatusCheck --> StatusOk{"允许登录?"}
StatusOk --> |否| ReturnStatus["返回状态拒绝错误"]
StatusOk --> |是| Success["记录成功并返回用户"]

注册服务(前台)

  • 协议单页保障:确保 agreement 页面存在
  • API 验证码 token:生成前端 token 与服务端哈希 token,用于无 session 场景下发验证码
  • 注册数据组装:统一处理 email/mobile、默认联系人 phone、推广关系直推/间推 ID
  • 事务化创建:用户表、SNS 绑定、默认联系人写入在同一事务中,异常回滚并记录日志
  • SNS 绑定/解绑:按 group 维度关联与移除
sequenceDiagram
participant Client as "客户端"
participant RegSvc as "RegistrationService"
participant DB as "数据库"
Client->>RegSvc : 提交注册数据
RegSvc->>DB : 事务开始
RegSvc->>DB : 插入用户(user)
RegSvc->>DB : 可选插入SNS绑定(user_sns)
RegSvc->>DB : upsert默认联系人(contact)
RegSvc->>DB : 提交事务
RegSvc-->>Client : 返回用户信息

用户核心服务(核心门面)

  • 资料读模型:构建基础资料、等级名称、按字段查找 user_id、当前等级、标准化格式化
  • 扩展身份:VIP/工作端/分销详情与布尔判断(受 features 开关控制)
  • 收货联系人:列表与完整地址拼装
  • 推广关系:解析 lineage、登记新会员关系树、随机 user_sn/头像文件名
classDiagram
class UserService {
+buildUserProfile(row, field) array
+levelName(level_id) string
+findUserId(keyword) mixed
+currentLevel(userId) array|null
+format(userOrId) array|false
+work(user_id) array|null
+vip(user_id) array|bool
+distribution(user_id) array|bool
+isVip(userId) bool
+isWork(userId) bool
+isDistribution(userId) bool
+contactList(user_id, current_contact_id) array
+addressFull(contact) string
+resolvePromotionLineage(userSn, selfUserId) array
+recordPromotionRelation(newUserId, directUserId) void
+randUserSn() string
+createAvatarFilename() string
}

认证服务(核心)

  • 登录态写入:
    • 前台:session 写入 user_id/shell/ontime/field,并生成静态 CSRF 令牌
    • API:签发不透明随机 token(服务端存储 sha256),明文仅一次返回
  • 记住我:生成持久化 token 并设置 Cookie(HttpOnly、SameSite、Secure)
  • 安全限流:
    • 登录失败计数与账户锁定(login_fail_count、login_locked_at)
    • IP 限流:基于 user_log 在窗口期内的失败次数
  • 登录态校验:校验 session shell 与用户密码一致性
sequenceDiagram
participant Controller as "控制器"
participant Auth as "UserAuthService"
participant DB as "数据库"
Controller->>Auth : login(user, field, remember)
alt API端
Auth->>DB : 更新登录次数
Auth->>Auth : issue API Token
Auth-->>Controller : {user_id, token, field}
else 前台Session
Auth->>DB : 更新登录次数
Auth->>Auth : 生成shell/写入session
Auth-->>Controller : 登录成功
end

会员等级服务(核心)

  • 自动升级:按等级表顺序扫描,满足条件即升级并记录升级日志
  • 成长进度:计算当前值、目标值、百分比、下一等级名称与差值
  • 特性开关:仅在 features.user 开启且 user_level 表存在时生效
flowchart TD
S(["checkLevelUpgrade"]) --> Lock["锁行读取用户"]
Lock --> LoadLevels["加载等级列表"]
LoadLevels --> Scan{"从当前等级之后扫描"}
Scan --> |找到满足条件| Upgrade["更新level_id并记录日志"]
Scan --> |未找到| End(["结束"])
Upgrade --> Next["继续比较更高档"] --> Scan

统计服务(核心)

  • 单项统计:积分总额、余额总额、可用优惠券数量、收藏数量、累计消费、累计推广收益
  • 批量聚合:pointMap/moneyMap/consumptionMap/promoteMap,避免 N+1 查询
  • 特性开关:各统计项受对应 features.* 控制,关闭时返回 false 或空集合
classDiagram
class UserStatsService {
+totalPoint(user_id) mixed
+totalMoney(user_id) mixed
+totalCoupon(user_id) mixed
+totalFavorites(user_id) mixed
+totalConsumption(user_id) mixed
+totalPromote(user_id) mixed
+pointMap(userIds) array|false
+moneyMap(userIds) array|false
+consumptionMap(userIds) array
+promoteMap(userIds) array
}

后台用户服务(后台)

  • 列表展示:聚合最近登录时间、积分、余额、消费、推广、VIP 信息,支持状态筛选
  • 增删改:新增/更新用户、上传头像、维护默认联系人、审计日志
  • 批量操作:批量删除、Excel 导出(全部/选中)
  • 手工等级调整:记录 user_level_log/distribution_level_log
sequenceDiagram
participant Admin as "管理员"
participant AdminSvc as "UserService(后台)"
participant Stats as "UserStatsService"
participant DB as "数据库"
Admin->>AdminSvc : 请求用户列表
AdminSvc->>DB : 分页查询用户
AdminSvc->>Stats : pointMap/moneyMap/consumptionMap/promoteMap
Stats-->>AdminSvc : 聚合结果
AdminSvc-->>Admin : 渲染列表

依赖关系分析

  • 前台登录服务依赖核心认证服务进行限流、锁定、会话/Token 签发
  • 前台注册服务依赖核心用户服务进行推广关系解析与随机编号生成
  • 后台用户服务依赖核心统计服务进行批量聚合,提升列表性能
  • 等级服务依赖统计服务获取累计消费/推广值,驱动升级决策
graph LR
F_Login["前台登录服务"] --> C_Auth["核心认证服务"]
F_Reg["前台注册服务"] --> C_UserSvc["核心用户服务"]
A_Admin["后台用户服务"] --> C_Stats["核心统计服务"]
C_Level["核心等级服务"] --> C_Stats

性能考虑

  • 列表聚合优化:后台用户列表通过 pointMap/moneyMap/consumptionMap/promoteMap 批量聚合,避免逐条 N+1 查询
  • 统计缓存思路:UserStatsService 优先读取 user_wallet 快照,若无则回退到明细表最新一条 total,减少重复聚合
  • 登录限流:基于 user_log 的时间窗口计数,降低暴力破解风险的同时避免额外存储
  • 事务最小化:注册流程将用户、SNS、联系人写入同一事务,保证一致性与可回滚
  • 等级升级:使用 FOR UPDATE 锁行,防止并发升级导致重复升级

故障排查指南

  • 登录失败频繁被限流:检查 user_log 中 LOGIN_FAIL 动作在窗口期内的计数是否超过阈值
  • 账户被锁定:查看 user.login_locked_at 是否在未来时间;确认是否因连续失败触发
  • 密码验证失败:确认是否为历史 md5 格式;若命中会尝试升级 bcrypt,否则按 bcrypt 校验
  • 注册失败:检查事务是否回滚,关注日志中的异常信息与入参(email/mobile/SNS)
  • 等级未升级:确认 features.user 是否开启、user_level 表是否存在且有序;核对累计消费/推广值是否达标
  • 统计为空:确认对应 features.* 开关是否启用;检查 user_wallet 快照或明细表是否有数据

结论

DouPHP 用户服务通过清晰的分层与职责划分,实现了高内聚、低耦合的安全认证、等级与统计体系。前台服务专注交互编排,核心服务提供跨端复用能力,后台服务在此基础上增强管理与审计。通过特性开关与批量聚合,系统在可扩展性与性能之间取得平衡。

附录:使用示例与扩展建议

  • 用户注册与登录
    • 前台注册:调用 RegistrationService.ensureAgreementPageExists 确保协议页;使用 createApiVerificationToken 生成验证码 token;通过 createUser 事务化创建用户并绑定默认联系人
    • 前台登录:调用 LoginService.validateLoginCredentials 进行凭据校验;成功后由控制器决定写 session 或签发 API Token
  • 权限与状态管理
    • 后台修改状态:调用 UserService.setStatus,内部校验合法迁移并写审计日志
    • 登录态校验:使用 UserAuthService.checkLoginState 校验 session shell 有效性
  • 会员等级与积分
    • 等级升级:在订单完成后调用 UserLevelService.checkLevelUpgrade,自动升级并记录日志
    • 积分/余额:通过 UserStatsService.totalPoint/totalMoney 获取当前值;后台列表使用 pointMap/moneyMap 批量聚合
  • 与其他模块集成
    • 订单服务:UserStatsService.totalConsumption 基于 order 表统计,结合 OrderStatus 过滤已支付/已完成订单
    • 营销服务:UserStatsService.totalCoupon 统计可用优惠券数量;UserStatsService.totalPromote 统计推广收益
    • 内容服务:favorites 收藏数通过 UserStatsService.totalFavorites 统计
  • 扩展建议
    • 新增统计指标:参照 UserStatsService 的 features.* 开关与 latestTotalMap 模式,增加新的聚合方法
    • 扩展认证方式:在 LoginService 中新增凭据类型识别分支,保持审计与限流一致
    • 扩展等级规则:在 user_level 表中添加新 upgrade_type 与条件,UserLevelService 会自动纳入升级循环
添加日期:2026-10-05