# RBAC 权限控制详解

## 📚 什么是 RBAC？

**RBAC（Role-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` 组成：

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

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

### 2. **创建角色并分配权限**

```typescript
// 创建管理员角色
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. **给用户分配角色**

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

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

#### 方式一：使用角色装饰器

```typescript
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() {
    // 只有管理员可以删除用户
  }
}
```

#### 方式二：使用权限装饰器（可扩展）

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

### 5. **获取用户权限**

```typescript
// 在 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 Token，Token 中包含用户 ID

### 2. **JwtAuthGuard**

验证 JWT Token，提取用户信息

### 3. **RolesGuard**

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

### 4. **权限获取**

登录时，系统会：

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

### 5. **前端权限控制**

前端可以根据返回的 `roles` 和 `permissions` 数组：

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

## 📝 最佳实践

### 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. ✅ 登录时返回用户的角色和权限列表

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