简介
本技术文档围绕 DouPHP 的用户服务,系统说明其职责边界、关键实现与集成方式。重点覆盖:
- 用户注册登录流程(含凭据校验与会话/令牌签发)
- 权限与身份管理(VIP、工作端、分销等扩展身份)
- 会员等级与成长值体系
- 积分与余额统计
- 安全机制(密码加密、会话管理、防暴力破解)
- 数据隐私保护、性能优化与扩展性设计
项目结构
用户域能力分布在 core 层与 admin/front/api 各层:
- core/service/user:用户认证、密码、等级、统计、资料查询、推广关系等通用能力
- admin/service/user:后台会员管理(列表、新增、编辑、删除、批量操作、导出)
- front/_/module/user:前台登录凭据校验与服务编排(登录、注册、手机登录等)
graph TB
subgraph "核心服务(core)"
A["UserService<br/>薄编排门面"]
B["UserAuthService<br/>登录/会话/令牌/限流"]
C["UserPasswordService<br/>改密"]
D["UserLevelService<br/>等级升级/成长值"]
E["UserStatsService<br/>积分/余额/消费/推广统计"]
end
subgraph "后台(admin)"
F["Admin UserService<br/>CRUD/批量/导出"]
end
subgraph "前台(front)"
G["LoginService<br/>凭据校验(不写状态)"]
end
A --> B
A --> D
A --> E
F --> A
F --> E
G --> B
核心组件
- 用户服务门面(core/service/user/UserService):组合资料查询、扩展身份、联系人、推广关系等子能力,提供稳定对外签名。
- 认证服务(core/service/user/UserAuthService):负责登录态写入(Session/Token)、记住我、失败锁定、IP 速率限制与会话校验。
- 密码服务(core/service/user/UserPasswordService):统一原密码校验与新密码更新,兼容历史 md5,并吊销 API Token。
- 等级服务(core/service/user/UserLevelService):按消费/推广指标自动升级,记录日志,计算成长值进度。
- 统计服务(core/service/user/UserStatsService):积分、余额、优惠券、收藏、累计消费、推广收益的单条与批量查询。
- 后台用户服务(admin/service/user/UserService):会员列表、新增、编辑、删除、批量操作、Excel 导出、手工等级调整日志。
- 前台登录服务(_/module/user/front/service/user/LoginService):仅做凭据校验,不写 Session/Cookie;由调用方决定写状态。
架构总览
用户域采用“薄编排门面 + 领域服务”的分层设计:
- 门面层(UserService)聚合多子服务,屏蔽内部复杂度,对外暴露稳定方法集。
- 领域服务层按关注点拆分:认证、密码、等级、统计、资料、推广等。
- 调用方通过 facade 或容器注入使用,避免直接耦合数据库与配置。
sequenceDiagram
participant Client as "客户端"
participant Front as "前台控制器"
participant LoginSvc as "LoginService"
participant AuthSvc as "UserAuthService"
participant DB as "数据库"
Client->>Front : 提交登录表单
Front->>LoginSvc : 校验用户名/密码
LoginSvc->>DB : 读取用户与密码哈希
LoginSvc-->>Front : 返回 user 行或错误
Front->>AuthSvc : 登录成功则写入会话/令牌
AuthSvc->>DB : 更新登录次数/失败计数
AuthSvc-->>Front : 返回登录结果
Front-->>Client : 跳转或返回 token
详细组件分析
用户服务门面(core/service/user/UserService)
- 职责:组合 UserProfileQuery、UserMembershipQuery、UserContactQuery、UserPromotionService,提供资料构建、等级名称、当前等级、联系人列表、推广关系解析、随机编号/头像名生成等能力。
- 设计要点:以“薄编排”形式对外暴露稳定签名,便于前后台复用;子服务可独立注入或模块化获取。
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
}
认证与会话(core/service/user/UserAuthService)
- 登录流程:根据 IS_API 分支签发不透明 token 或写入 Session(user_id/shell/ontime/field),并递增登录次数。
- 记住我:生成并持久化 token 到 user 表与 Cookie。
- 防暴力破解:维护 login_fail_count 与 login_locked_at,支持 IP 窗口内失败次数限制。
- 会话校验:checkLoginState 基于 shell 校验会话有效性。
flowchart TD
Start(["登录入口"]) --> CheckAPI{"是否API端?"}
CheckAPI --> |是| IssueToken["签发不透明token"]
CheckAPI --> |否| WriteSession["写入Session(user_id/shell/ontime/field)"]
IssueToken --> UpdateCount["更新登录次数"]
WriteSession --> UpdateCount
UpdateCount --> Remember{"是否记住我?"}
Remember --> |是| SetCookie["写入token到Cookie"]
Remember --> |否| End(["完成"])
SetCookie --> End
密码管理(core/service/user/UserPasswordService)
- 兼容历史 md5:若旧密码为 32 位十六进制,优先 md5 校验,通过后升级为 bcrypt。
- 新密码统一以 bcrypt 存储。
- 改密后吊销该用户全部 API Token,确保安全性。
flowchart TD
S(["修改密码请求"]) --> ReadPwd["读取用户密码哈希"]
ReadPwd --> Verify{"原密码校验"}
Verify --> |失败| Err["返回错误"]
Verify --> |成功| Upgrade{"是否md5?"}
Upgrade --> |是| ToBcrypt["立即升级为bcrypt"]
Upgrade --> |否| Skip["跳过升级"]
ToBcrypt --> Save["保存新密码(bcrypt)"]
Skip --> Save
Save --> Revoke["吊销该用户所有API Token"]
Revoke --> Log["记录审计日志"]
Log --> Done(["完成"])
会员等级与成长值(core/service/user/UserLevelService)
- 自动升级:在事务中加锁读取用户,遍历等级表,按消费/推广指标判断升级,写入 user_level_log。
- 成长值展示:计算当前值、目标值、百分比、下一等级名称与差距提示。
- 降级/手动调整:后台可手工调整等级并记录日志。
sequenceDiagram
participant Caller as "调用方"
participant LevelSvc as "UserLevelService"
participant DB as "数据库"
participant Stats as "UserStatsService"
Caller->>LevelSvc : checkLevelUpgrade(user_id, order_sn)
LevelSvc->>DB : 开启事务/加锁读用户
LevelSvc->>Stats : totalConsumption / totalPromote
LevelSvc->>DB : 读取等级表
LevelSvc->>DB : 满足条件则更新level_id并写日志
LevelSvc-->>Caller : 返回是否升级
统计与账户(core/service/user/UserStatsService)
- 单条查询:积分总额、余额总额、可用优惠券数、收藏数、累计消费、推广收益。
- 批量查询:pointMap/moneyMap/consumptionMap/promoteMap,消除 N+1 查询,提升列表性能。
- 特性开关:依据 features.point/money/order/coupon/favorites 控制功能可用性。
flowchart TD
Q(["批量统计请求"]) --> Normalize["归一化用户ID集合"]
Normalize --> QueryPoint{"features.point?"}
QueryPoint --> |是| MapPoint["latestTotalMap('point')"]
QueryPoint --> |否| SkipPoint["返回false"]
Normalize --> QueryMoney{"features.money?"}
QueryMoney --> |是| MapMoney["latestTotalMap('money')"]
QueryMoney --> |否| SkipMoney["返回false"]
Normalize --> QueryOrder{"features.order?"}
QueryOrder --> |是| SumOrder["SUM(order_amount)"]
QueryOrder --> |否| EmptyOrder["返回空数组"]
Normalize --> QueryPromote{"features.money?"}
QueryPromote --> |是| SumPromote["SUM(money)"]
QueryPromote --> |否| EmptyPromote["返回空数组"]
MapPoint --> Merge["合并结果"]
MapMoney --> Merge
SumOrder --> Merge
SumPromote --> Merge
SkipPoint --> Merge
SkipMoney --> Merge
EmptyOrder --> Merge
EmptyPromote --> Merge
Merge --> Return(["返回映射"])
后台用户管理(admin/service/user/UserService)
- 列表:支持按关键字(手机号/邮箱/user_sn/联系人)过滤,聚合最后登录、积分、余额、消费、推广、VIP 信息。
- 新增/编辑:字段白名单与校验由 Request 承担;新增时生成 user_sn、设置等级、写入默认联系人、上传头像、记录审计日志。
- 删除/批量:支持确认删除、批量删除、Excel 导出。
- 手工等级调整:写入 user_level_log/distribution_level_log。
sequenceDiagram
participant Admin as "管理员"
participant Ctrl as "后台控制器"
participant USvc as "Admin UserService"
participant DB as "数据库"
Admin->>Ctrl : 提交新增/编辑表单
Ctrl->>USvc : insert/update(data)
USvc->>DB : 写入用户/联系人/头像
USvc->>DB : 记录等级变更日志
USvc-->>Ctrl : 返回结果
Ctrl-->>Admin : 成功提示/返回列表
前台登录凭据校验(_/module/user/front/service/user/LoginService)
- 职责:仅校验凭据,返回 user 行或错误;不写 Session/Cookie。
- 兼容历史 md5:命中 md5 后立即升级为 bcrypt。
- 状态检查:校验用户状态,防止被封禁账号登录。
sequenceDiagram
participant FC as "前台控制器"
participant LS as "LoginService"
participant DB as "数据库"
FC->>LS : 校验用户名/密码
LS->>DB : 读取用户与密码
LS->>LS : 兼容md5并升级
LS->>LS : 检查用户状态
LS-->>FC : 返回user或errors
依赖关系分析
- UserService 依赖多个子服务(资料、身份、联系人、推广),形成稳定的门面接口。
- UserAuthService 依赖 DB、Session、ApiTokenService,集中处理登录态与安全策略。
- UserLevelService 依赖 UserStatsService 获取消费/推广指标,结合配置与表存在性决定是否启用等级功能。
- Admin UserService 依赖 UserStatsService、UserLogQuery、UserMembershipQuery、UserContactQuery 完成列表聚合与管理操作。
graph LR
US["UserService"] --> PQ["UserProfileQuery"]
US --> MQ["UserMembershipQuery"]
US --> CQ["UserContactQuery"]
US --> PS["UserPromotionService"]
UA["UserAuthService"] --> DB["DB"]
UA --> SESS["Session"]
UA --> AT["ApiTokenService"]
UL["UserLevelService"] --> ST["UserStatsService"]
AU["Admin UserService"] --> ST
AU --> LQ["UserLogQuery"]
AU --> MQ
AU --> CQ
性能考虑
- 列表聚合:后台用户列表通过批量 map 方法(pointMap/moneyMap/consumptionMap/promoteMap)减少 N+1 查询。
- 事务与锁:等级升级使用事务与 FOR UPDATE 保证并发安全。
- 特性开关:统计与等级功能通过 features.* 配置按需启用,避免不必要的数据访问。
- 会话与令牌:API 端使用不透明 token,前端 Session 使用 shell 校验,降低重复鉴权开销。
故障排查指南
- 登录失败锁定:检查 user.login_fail_count 与 login_locked_at,必要时重置。
- 会话失效:核对 session 中的 user_id/shell/ontime/field 是否与当前用户一致。
- 等级未升级:确认 features.user 已启用且 user_level 表存在;检查消费/推广指标是否达到阈值。
- 统计异常:确认 features.point/money/order/coupon/favorites 配置是否正确;核对订单状态与 money 动作类型。
结论
DouPHP 用户服务通过清晰的分层与模块化设计,将认证、密码、等级、统计、资料与推广关系解耦,既保证了业务能力的可扩展性,又提升了可维护性与性能表现。配合严格的安全策略(bcrypt、会话校验、失败锁定、IP 限流)与特性开关,能够灵活适配不同部署场景。
附录:开发示例与最佳实践
-
用户注册
- 前台注册:控制器接收表单,调用对应服务创建用户并写入默认联系人;第三方登录时同步 SNS 信息。
- 参考路径:_/module/user/front/controller/user/AuthController.php
-
登录验证
- 前台:先通过 LoginService 校验凭据,再调用 UserAuthService 写入 Session 或签发 API Token。
- 参考路径:_/module/user/front/service/user/LoginService.php:113-143, core/service/user/UserAuthService.php:41-74
-
权限检查
- 使用 UserService::isVip/isWork/isDistribution 快速判断扩展身份;结合后台 VIP 列表单元格构建逻辑进行展示。
- 参考路径:core/service/user/UserService.php:174-214, admin/service/user/UserService.php:240-255
-
用户信息更新
- 后台:Admin UserService::update 支持更新基本信息、等级、联系人、头像,并记录审计日志。
- 参考路径:admin/service/user/UserService.php:407-465
-
安全机制
- 密码加密:统一使用 bcrypt,兼容历史 md5 并即时升级。
- 会话管理:Session 包含 shell 校验;API 使用不透明 token。
- 防暴力破解:失败计数与锁定时间;IP 窗口内失败次数限制。
- 参考路径:core/service/user/UserPasswordService.php:43-75, core/service/user/UserAuthService.php:152-211
-
数据隐私保护
- 最小化输出:列表与详情仅返回必要字段;敏感字段(如密码)不输出。
- 审计日志:关键操作(状态变更、删除、等级调整)均记录审计日志。
- 参考路径:admin/service/user/UserService.php:203-229, admin/service/user/UserService.php:475-501
-
性能优化
- 批量统计:使用 pointMap/moneyMap/consumptionMap/promoteMap 减少数据库往返。
- 事务与锁:等级升级使用事务与 FOR UPDATE 避免竞态。
- 参考路径:core/service/user/UserStatsService.php:209-337, core/service/user/UserLevelService.php:60-141
-
扩展性设计
- 门面聚合:UserService 作为门面,便于新增子能力而不影响调用方。
- 特性开关:通过 features.* 控制模块启用,便于灰度与裁剪。
- 参考路径:core/service/user/UserService.php:39-69, core/service/user/UserLevelService.php:56-58