Account模块
账号模块管理用户身份资料与账户生命周期,并与认证、凭据和资源授权保持明确的职责边界。
Account模块
[!info] related notes
- 相关业务: Authentication模块, 认证业务
- 认证与登录: Token认证的实现流程, Cookie、Session、Token
- 关联实现: 账号信息记录功能实现, express实现登录
Overview
本文描述通用模块职责,不声明某个项目已经采用下面的表或服务拆分。Account 管理用户标识、档案和账户状态;Authentication 验证身份并维护会话;Authorization 判断是否允许对资源执行动作。
注册通常需要 Account 与 Auth 协作。注销账户是账户生命周期变化;退出登录是会话操作,两者不能混用。
本地账号列表与自动登录的区别见 account-info-logging-implementation。账号卡片只能发起认证恢复,不能凭本地 user ID 直接获得权限。
服务
基础信息服务 (Base Profile Service)
用户资料常被读取;是否引入缓存取决于实际负载和一致性要求。
- 查询用户详情: 获取昵称、头像、简介、注册时间。
- 批量查询: 供其他模块调用(例如:评论模块需要显示 10 个用户的头像)。
- 更新资料: 修改非敏感信息(如生日、地区、个人简介)。
安全与状态服务 (Security & State Service)
- 状态变更: 管理员封禁/解封用户、用户注销(软删除)。
- 敏感操作记录: 记录“修改密码”、“更换手机号”等操作日志(Audit Log)。
数据库设计(Database Schema)
以下为 MySQL 风格的示意表,展示用户主体与展示资料的拆分,不是可直接上线的完整 schema。凭据管理见 authentication-module;模块拆分不要求拆成多个数据库。
用户主表 (users / user_base)
这是系统的“身份证”,只存最核心、改动频率最低的数据。
CREATE TABLE users (
id BIGINT PRIMARY KEY, -- 用户唯一 ID;自增、UUID 或分布式 ID 按系统约束选择
username VARCHAR(64) UNIQUE, -- 唯一用户名 (可选)
status TINYINT DEFAULT 1, -- 状态: 1-正常, 2-锁定, 3-注销, 0-未激活
created_at DATETIME, -- 注册时间
updated_at DATETIME -- 最后更新时间
);
用户扩展信息表 (user_profiles)
可将展示型数据独立存储;是否更高效取决于查询模式和 join 成本,不能只凭拆表保证性能。实际 schema 还需明确关联约束、必填字段和删除策略。
CREATE TABLE user_profiles (
user_id BIGINT PRIMARY KEY,
nickname VARCHAR(64), -- 昵称 (可以重复)
avatar_url VARCHAR(255), -- 头像链接
gender TINYINT, -- 性别
bio VARCHAR(500), -- 个人简介
preferences JSON -- 用户偏好设置 (夜间模式、语言等,用JSON存更灵活)
);
领域对象 (Domain Objects)
在代码实现(Java/Go/Node.ts)中,需要定义以下对象来承载数据:
1. 实体对象 (Entities/PO)
持久化对象通常对应数据库映射;领域实体表达业务身份与不变量,不一定与 ORM 表一一对应。
UserEntityUserIdentityEntityUserProfileEntity
2. 数据传输对象 (DTO - Data Transfer Object)
接口应显式选择允许返回的字段,避免 ORM 对象意外泄露 verifier、内部状态或个人资料。DTO 只是载体,定义了 DTO 也不等于已经做了字段级权限控制。
- 输入对象 (Request DTOs):
UpdateProfileRequest:{ nickname: string, bio: string }BindIdentityRequest:{ type: 'github', code: string }
- 输出对象 (Response DTOs):
UserCardVO:{ id, nickname, avatar }(轻量级,用于列表展示)UserDetailVO:{ id, username, email, phone, profile: {...}, settings: {...} }(全量级,用于“个人中心”)
Account 模块的关键业务流转
举个**“绑定新手机号”**的例子,看看 Account 模块内部怎么运作:
-
用户请求: 前端发起
POST /account/bind/phone,携带phoneNumber和verifyCode。 -
校验: 根据已认证的当前用户确认绑定权限,规范化手机号;查询是否已占用可用于提示,但不能代替数据库唯一约束。
-
验证: 验证码必须绑定该手机号、用途和有效期,并按一次性挑战消费;敏感绑定还应按策略重新认证。
-
写入: 在事务及唯一约束保护下绑定身份,处理并发冲突;不能采用无约束的“先查再插”。示意字段:
user_id: 当前登录用户type: ‘phone’identifier: +86138xxxx- 密码 verifier 由凭据模块管理,不因绑定手机号而自动生成初始密码
-
反馈: 返回绑定成功,前端刷新页面显示“手机号:已绑定”。
总结
Account 模块的核心在于解耦:
- 存储解耦: 身份(Identity)与档案(Profile)分开存。
- 逻辑解耦: Account 管理账户状态,Auth 管理认证和会话;封禁、恢复或注销等状态变化必须与会话策略衔接,不能只修改一列状态就假定旧凭据立即失效。