--- tags: [] aliases: - ER 图 date created: 星期二, 十二月 9日 2025, 10:45:43 晚上 date modified: 星期二, 十二月 9日 2025, 10:58:01 晚上 --- # ER 图 **设计思路分析:** 1. **RBAC 模型选择:** 为了满足“银行级权限控制”及“企业级样板间”的扩展性要求,我采用了标准的 **RBAC Level 1 (Flat RBAC)** 变体。虽然当前只有 3 个固定角色,但使用 **多对多 (Many-to-Many)** 的关联表 (`user_roles`) 能够支持未来某用户既是 "Editor" 又是 "TechLeader" 的混合权限场景,避免后续重构。 2. **双令牌机制落地:** 专门设计了 `refresh_tokens` 表。JWT 的 Access Token 是无状态的(不入库),但 Refresh Token 必须入库以实现“吊销”、“防重放”和“设备管理”功能。 3. **软删除与审计:** 所有核心表(`users`, `roles`)均继承了 Base Model,包含 `deleted_at` 字段。 --- ## 📊 阶段二:概念验证 (Conceptual Modeling - ER Diagram) ```mermaid erDiagram %% --------------------------------------------------------- %% 1. 用户核心表 (Users) %% 核心聚合根,包含认证凭证与个人资料 %% --------------------------------------------------------- users { bigint id PK "主键" string username "用户名, unique, not null" string password_hash "Argon2/Bcrypt 哈希值, not null" string nickname "用户昵称 (Profile)" string avatar_url "头像链接 (Profile)" string bio "个人简介 (Profile)" smallint status "状态: 1=Active, 0=Banned" timestamptz created_at "创建时间" timestamptz updated_at "更新时间" timestamptz deleted_at "软删除时间 (Soft Delete)" } %% --------------------------------------------------------- %% 2. 角色表 (Roles) %% 存储 Admin, Editor, Subscriber 等定义 %% --------------------------------------------------------- roles { bigint id PK "主键" string code "角色编码 (e.g. 'admin'), unique" string name "角色显示名称 (e.g. '超级管理员')" string description "备注" timestamptz created_at timestamptz updated_at timestamptz deleted_at } %% --------------------------------------------------------- %% 3. 用户-角色关联表 (User Roles) %% 中间表,实现 RBAC 多对多关系 %% --------------------------------------------------------- user_roles { bigint user_id FK "关联 users.id" bigint role_id FK "关联 roles.id" timestamptz created_at } %% --------------------------------------------------------- %% 4. 刷新令牌表 (Refresh Tokens) %% 用于双令牌机制的续期与风控 %% --------------------------------------------------------- refresh_tokens { bigint id PK "主键" bigint user_id FK "关联 users.id" string token_hash "Refresh Token 的哈希值 (安全考虑不存明文)" string family_id "令牌家族ID (用于检测重用/Rotation)" string parent_token_id "父令牌ID (用于溯源)" boolean is_revoked "是否已撤销 (黑名单机制)" timestamptz expires_at "过期时间 (7天)" timestamptz created_at } %% --------------------------------------------------------- %% 关系定义 (Relationships) %% --------------------------------------------------------- %% 一个用户可以拥有多个 Refresh Token (多设备登录) users ||--o{ refresh_tokens : "has_many (sessions)" %% 一个用户可以拥有多个角色 (扩展性设计) users ||--o{ user_roles : "assigned_to" %% 一个角色可以包含多个用户 roles ||--o{ user_roles : "includes" ``` --- ## 🔑 关键关系业务含义说明 1. **Users `||--o{` Refresh Tokens (1 对 多):** - **业务含义:** 一个用户可以在多个设备(手机、PC)同时登录。 - **风控逻辑:** 当用户执行“修改密码”或“严重违规封号”时,后端会根据 `user_id` 批量将该用户下的所有 `is_revoked` 设为 `true`,从而实现**强制下线**。 - **令牌轮转:** `family_id` 和 `parent_token_id` 用于检测令牌复用攻击。如果一个旧的 RT 被使用,系统可以根据 `family_id` 级联作废整个令牌链。 2. **Users `}|--|{` Roles (多 对 多,通过 `user_roles`):** - **业务含义:** 虽然 PRD 定义了三个层级,但物理模型采用“多对多”设计是架构上的**防御性编程**。 - **场景:** 如果未来需要赋予某个 Editor 临时的 Admin 权限,或者创建一个 "SuperSubscriber"(付费会员),我们只需在 `user_roles` 插入一条记录,而无需修改表结构。 3. **Users 表的混合设计:** - **决策:** 我没有将 `Profile` (昵称/头像) 拆分为独立表。 - **理由:** 遵循“勿增实体”原则。在当前 V1 阶段,Profile 字段较少(仅 3 个),且在列表页展示时(如“评论列表”)属于高频连表查询。合并不仅减少了 JOIN 开销,也简化了 GORM 的模型编写。