library-picturebook-activity/backend/docs/RBAC_GUIDE.md
aid 418aa57ea8 Day4: 超管端设计优化 + UGC绘本创作社区P0实现
一、超管端设计优化
- 文档管理SOP体系建立,docs目录重组
- 统一用户管理:跨租户全局视角,合并用户管理+公众用户
- 活动监管全模块重构:全部活动(统计卡片+阶段筛选+SuperDetail详情页)、报名数据/作品数据/评审进度(两层合一扁平列表)、成果发布(去Tab+统计+隐藏写操作)
- 菜单精简:移除评委管理/评审规则/通知管理
- Bug修复:租户编辑丢失隐藏菜单、pageSize限制、主色统一

二、UGC绘本创作社区P0
- 数据库:10张新表(user_works/user_work_pages/work_tags等)
- 子女账号独立化:Child升级为独立User,家长切换+独立登录
- 用户作品库:CRUD+发布审核,8个API
- AI创作流程:提交→生成→保存到作品库,4个API
- 作品广场:首页改造为推荐流,标签+搜索+排序
- 内容审核(超管端):作品审核+作品管理+标签管理
- 活动联动:WorkSelector作品选择器
- 布局改造:底部5Tab(发现/创作/活动/作品库/我的)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 22:20:25 +08:00

9.0 KiB
Raw Blame History

RBAC 权限控制详解

📚 什么是 RBAC

RBACRole-Based Access Control基于角色的访问控制,是一种权限管理模型。它的核心思想是:

用户 → 角色 → 权限

通过给用户分配角色,角色拥有权限,从而间接地给用户授予权限。

🎯 RBAC 的核心概念

1. 用户User

系统中的实际使用者,如:张三、李四

2. 角色Role

一组权限的集合,如:管理员、编辑、访客

3. 权限Permission

对资源的操作能力,如:创建用户、删除文章、查看报表

4. 资源Resource

系统中的实体对象,如:用户、文章、订单

5. 操作Action

对资源的操作类型create创建、read查看、update更新、delete删除

🏗️ 项目中的 RBAC 架构

数据模型关系

User (用户)
  ↓ (多对多)
UserRole (用户角色关联)
  ↓
Role (角色)
  ↓ (多对多)
RolePermission (角色权限关联)
  ↓
Permission (权限)
  ├─ resource: 资源名称 (如: user, role, menu)
  └─ action: 操作类型 (如: create, read, update, delete)

数据库表结构

1. users - 用户表

存储系统用户的基本信息

2. roles - 角色表

存储角色信息,如:

  • admin - 管理员
  • editor - 编辑
  • viewer - 查看者

3. permissions - 权限表

存储权限信息,权限由 resource + action 组成,如:

  • user:create - 创建用户
  • user:read - 查看用户
  • user:update - 更新用户
  • user:delete - 删除用户
  • role:create - 创建角色
  • menu:read - 查看菜单

4. user_roles - 用户角色关联表

用户和角色的多对多关系

5. role_permissions - 角色权限关联表

角色和权限的多对多关系

🔄 RBAC 工作流程

1. 权限分配流程

1. 创建权限
   └─> 定义资源resource和操作action
       └─> 例如user:create, user:read

2. 创建角色
   └─> 给角色分配权限
       └─> 例如:管理员角色 = [user:create, user:read, user:update, user:delete]

3. 给用户分配角色
   └─> 用户继承角色的所有权限
       └─> 例如:张三 = 管理员角色

2. 权限验证流程

用户请求 API
  ↓
JWT 认证(验证用户身份)
  ↓
提取用户信息(包含 roles 和 permissions
  ↓
RolesGuard 检查(检查用户是否有指定角色)
  ↓
PermissionGuard 检查(检查用户是否有指定权限)
  ↓
允许/拒绝访问

💻 代码实现示例

1. 定义权限

权限由 resource + action 组成:

// 权限示例
{
  code: 'user:create',      // 权限编码
  resource: 'user',         // 资源:用户
  action: 'create',         // 操作:创建
  name: '创建用户',
  description: '允许创建新用户'
}

{
  code: 'user:read',
  resource: 'user',
  action: 'read',
  name: '查看用户',
  description: '允许查看用户列表和详情'
}

2. 创建角色并分配权限

// 创建管理员角色
const adminRole = await prisma.role.create({
  data: {
    name: '管理员',
    code: 'admin',
    permissions: {
      create: [
        { permission: { connect: { code: 'user:create' } } },
        { permission: { connect: { code: 'user:read' } } },
        { permission: { connect: { code: 'user:update' } } },
        { permission: { connect: { code: 'user:delete' } } },
        { permission: { connect: { code: 'role:create' } } },
        // ... 更多权限
      ],
    },
  },
});

3. 给用户分配角色

// 给用户分配管理员角色
await prisma.userRole.create({
  data: {
    user: { connect: { id: userId } },
    role: { connect: { code: 'admin' } },
  },
});

4. 在控制器中使用权限控制

方式一:使用角色装饰器

import { Controller, Get, UseGuards } from '@nestjs/common';
import { Roles } from '../auth/decorators/roles.decorator';
import { RolesGuard } from '../auth/guards/roles.guard';

@Controller('users')
@UseGuards(RolesGuard)
export class UsersController {
  @Get()
  @Roles('admin', 'editor') // 需要 admin 或 editor 角色
  findAll() {
    // 只有拥有 admin 或 editor 角色的用户才能访问
  }

  @Delete(':id')
  @Roles('admin') // 只有 admin 角色可以删除
  remove() {
    // 只有管理员可以删除用户
  }
}

方式二:使用权限装饰器(可扩展)

// 可以创建 PermissionGuard 和 @Permissions() 装饰器
@Get()
@Permissions('user:read')  // 需要 user:read 权限
findAll() {
  // 只有拥有 user:read 权限的用户才能访问
}

5. 获取用户权限

// 在 AuthService 中
private async getUserPermissions(userId: number): Promise<string[]> {
  const user = await this.usersService.findOne(userId);
  if (!user) return [];

  const permissions = new Set<string>();

  // 遍历用户的所有角色
  user.roles?.forEach((ur: any) => {
    // 遍历角色的所有权限
    ur.role.permissions?.forEach((rp: any) => {
      permissions.add(rp.permission.code);
    });
  });

  return Array.from(permissions);
  // 返回: ['user:create', 'user:read', 'user:update', 'role:create', ...]
}

📊 RBAC 的优势

1. 灵活性

  • 一个用户可以有多个角色
  • 一个角色可以有多个权限
  • 权限可以动态分配和回收

2. 可维护性

  • 权限变更只需修改角色,不需要逐个修改用户
  • 角色可以复用,减少重复配置

3. 可扩展性

  • 新增资源只需添加新的权限
  • 新增角色只需组合现有权限

4. 安全性

  • 最小权限原则:用户只获得必要的权限
  • 权限集中管理,便于审计

🎨 实际应用场景

场景 1内容管理系统

角色定义:
- 超级管理员:所有权限
- 内容管理员:文章 CRUD、评论管理
- 编辑:文章创建、编辑
- 作者:文章创建
- 访客:文章查看

权限示例:
- article:create
- article:read
- article:update
- article:delete
- comment:moderate

场景 2电商系统

角色定义:
- 平台管理员:所有权限
- 店铺管理员:店铺管理、订单管理
- 客服:订单查看、退款处理
- 财务:订单查看、财务报表

权限示例:
- order:create
- order:read
- order:update
- order:refund
- report:financial

🔐 项目中的权限控制实现

1. JWT 认证

用户登录后获得 JWT TokenToken 中包含用户 ID

2. JwtAuthGuard

验证 JWT Token提取用户信息

3. RolesGuard

检查用户是否拥有指定的角色

4. 权限获取

登录时,系统会:

  1. 查询用户的所有角色
  2. 查询角色关联的所有权限
  3. 合并所有权限并返回给前端

5. 前端权限控制

前端可以根据返回的 rolespermissions 数组:

  • 控制菜单显示
  • 控制按钮显示
  • 控制路由访问

📝 最佳实践

1. 权限命名规范

格式resource:action
示例:
- user:create
- user:read
- user:update
- user:delete
- role:assign
- menu:manage

2. 角色命名规范

使用有意义的英文代码:
- admin: 管理员
- editor: 编辑
- viewer: 查看者
- guest: 访客

3. 权限粒度

  • 不要过粗:避免一个权限包含太多操作
  • 不要过细:避免权限过多难以管理
  • 按业务模块划分user、role、menu、dict 等

4. 默认角色

建议创建以下默认角色:

  • 超级管理员:拥有所有权限
  • 普通用户:基础查看权限
  • 访客:只读权限

🚀 扩展功能

1. 权限继承

可以实现角色继承,子角色继承父角色的权限

2. 动态权限

可以根据数据范围动态控制权限,如:

  • 用户只能管理自己创建的订单
  • 部门管理员只能管理本部门的用户

3. 权限缓存

将用户权限缓存到 Redis提高性能

4. 权限审计

记录权限变更日志,便于追溯

📖 总结

RBAC 权限控制通过 用户 → 角色 → 权限 的三层关系,实现了灵活、可维护的权限管理系统。在你的项目中:

  1. 用户 通过 user_roles 表关联 角色
  2. 角色 通过 role_permissions 表关联 权限
  3. 权限resource + action 组成
  4. 使用 @Roles() 装饰器控制接口访问
  5. 登录时返回用户的角色和权限列表

这样的设计既保证了安全性,又提供了良好的扩展性和可维护性!