library-picturebook-activity/backend/docs/RBAC_GUIDE.md

398 lines
8.6 KiB
Markdown
Raw Permalink Normal View History

2025-11-23 14:04:20 +08:00
# 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` 组成:
```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 TokenToken 中包含用户 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. ✅ 登录时返回用户的角色和权限列表
这样的设计既保证了安全性,又提供了良好的扩展性和可维护性!