8.6 KiB
8.6 KiB
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 组成:
// 权限示例
{
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 Token,Token 中包含用户 ID
2. JwtAuthGuard
验证 JWT Token,提取用户信息
3. RolesGuard
检查用户是否拥有指定的角色
4. 权限获取
登录时,系统会:
- 查询用户的所有角色
- 查询角色关联的所有权限
- 合并所有权限并返回给前端
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 权限控制通过 用户 → 角色 → 权限 的三层关系,实现了灵活、可维护的权限管理系统。在你的项目中:
- ✅ 用户 通过
user_roles表关联 角色 - ✅ 角色 通过
role_permissions表关联 权限 - ✅ 权限 由
resource+action组成 - ✅ 使用
@Roles()装饰器控制接口访问 - ✅ 登录时返回用户的角色和权限列表
这样的设计既保证了安全性,又提供了良好的扩展性和可维护性!