# RBAC 权限控制使用示例 ## 📋 目录 1. [基础使用](#基础使用) 2. [角色控制示例](#角色控制示例) 3. [权限控制示例](#权限控制示例) 4. [完整示例](#完整示例) ## 🔧 基础使用 ### 1. 创建权限 ```typescript // 在数据库中创建权限 const permissions = [ { code: 'user:create', resource: 'user', action: 'create', name: '创建用户' }, { code: 'user:read', resource: 'user', action: 'read', name: '查看用户' }, { code: 'user:update', resource: 'user', action: 'update', name: '更新用户' }, { code: 'user:delete', resource: 'user', action: 'delete', name: '删除用户' }, { code: 'role:create', resource: 'role', action: 'create', name: '创建角色' }, { code: 'role:read', resource: 'role', action: 'read', name: '查看角色' }, ]; for (const perm of permissions) { await prisma.permission.create({ data: perm }); } ``` ### 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' } } }, { permission: { connect: { code: 'role:read' } } }, ] } } }); // 创建编辑角色(只有查看和更新权限) const editorRole = await prisma.role.create({ data: { name: '编辑', code: 'editor', permissions: { create: [ { permission: { connect: { code: 'user:read' } } }, { permission: { connect: { code: 'user:update' } } }, ] } } }); ``` ### 3. 给用户分配角色 ```typescript // 给用户分配管理员角色 await prisma.userRole.create({ data: { user: { connect: { id: 1 } }, role: { connect: { code: 'admin' } } } }); // 用户可以有多个角色 await prisma.userRole.create({ data: { user: { connect: { id: 1 } }, role: { connect: { code: 'editor' } } } }); ``` ## 🎯 角色控制示例 ### 在控制器中使用角色装饰器 ```typescript import { Controller, Get, Post, Delete, UseGuards } from '@nestjs/common'; import { Roles } from '../auth/decorators/roles.decorator'; import { RolesGuard } from '../auth/guards/roles.guard'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; @Controller('users') @UseGuards(JwtAuthGuard, RolesGuard) // 先验证 JWT,再验证角色 export class UsersController { // 所有已登录用户都可以查看 @Get() findAll() { return this.usersService.findAll(); } // 只有管理员和编辑可以创建用户 @Post() @Roles('admin', 'editor') create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); } // 只有管理员可以删除用户 @Delete(':id') @Roles('admin') remove(@Param('id') id: string) { return this.usersService.remove(+id); } } ``` ## 🔐 权限控制示例 ### 创建权限守卫(可选扩展) ```typescript // src/auth/guards/permissions.guard.ts import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; @Injectable() export class PermissionsGuard implements CanActivate { constructor(private reflector: Reflector) {} canActivate(context: ExecutionContext): boolean { const requiredPermissions = this.reflector.getAllAndOverride( 'permissions', [context.getHandler(), context.getClass()], ); if (!requiredPermissions) { return true; // 没有权限要求,允许访问 } const { user } = context.switchToHttp().getRequest(); const userPermissions = user.permissions || []; // 检查用户是否拥有任一所需权限 return requiredPermissions.some((permission) => userPermissions.includes(permission), ); } } ``` ### 创建权限装饰器 ```typescript // src/auth/decorators/permissions.decorator.ts import { SetMetadata } from '@nestjs/common'; export const PERMISSIONS_KEY = 'permissions'; export const Permissions = (...permissions: string[]) => SetMetadata(PERMISSIONS_KEY, permissions); ``` ### 使用权限控制 ```typescript import { Controller, Get, Post, Delete, UseGuards } from '@nestjs/common'; import { Permissions } from '../auth/decorators/permissions.decorator'; import { PermissionsGuard } from '../auth/guards/permissions.guard'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; @Controller('users') @UseGuards(JwtAuthGuard, PermissionsGuard) export class UsersController { @Get() @Permissions('user:read') // 需要 user:read 权限 findAll() { return this.usersService.findAll(); } @Post() @Permissions('user:create') // 需要 user:create 权限 create(@Body() createUserDto: CreateUserDto) { return this.usersService.create(createUserDto); } @Delete(':id') @Permissions('user:delete') // 需要 user:delete 权限 remove(@Param('id') id: string) { return this.usersService.remove(+id); } } ``` ## 📚 完整示例 ### 完整的用户管理控制器 ```typescript import { Controller, Get, Post, Body, Patch, Param, Delete, Query, UseGuards, Request, } from '@nestjs/common'; import { UsersService } from './users.service'; import { CreateUserDto } from './dto/create-user.dto'; import { UpdateUserDto } from './dto/update-user.dto'; import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard'; import { RolesGuard } from '../auth/guards/roles.guard'; import { Roles } from '../auth/decorators/roles.decorator'; @Controller('users') @UseGuards(JwtAuthGuard) // 所有接口都需要登录 export class UsersController { constructor(private readonly usersService: UsersService) {} // 查看用户列表 - 所有已登录用户都可以访问 @Get() findAll(@Query('page') page?: string, @Query('pageSize') pageSize?: string) { return this.usersService.findAll( page ? parseInt(page) : 1, pageSize ? parseInt(pageSize) : 10, ); } // 查看用户详情 - 所有已登录用户都可以访问 @Get(':id') findOne(@Param('id') id: string) { return this.usersService.findOne(+id); } // 创建用户 - 需要 admin 或 editor 角色 @Post() @UseGuards(RolesGuard) @Roles('admin', 'editor') create(@Body() createUserDto: CreateUserDto, @Request() req) { // req.user 包含当前用户信息(从 JWT 中提取) return this.usersService.create(createUserDto); } // 更新用户 - 需要 admin 角色,或者用户自己更新自己 @Patch(':id') @UseGuards(RolesGuard) async update( @Param('id') id: string, @Body() updateUserDto: UpdateUserDto, @Request() req, ) { const userId = parseInt(id); const currentUserId = req.user.userId; // 管理员可以更新任何人,普通用户只能更新自己 if (req.user.roles?.includes('admin') || userId === currentUserId) { return this.usersService.update(userId, updateUserDto); } throw new ForbiddenException('无权更新此用户'); } // 删除用户 - 只有管理员可以删除 @Delete(':id') @UseGuards(RolesGuard) @Roles('admin') remove(@Param('id') id: string) { return this.usersService.remove(+id); } } ``` ## 🔍 权限检查流程 ### 1. 用户登录 ```typescript // POST /api/auth/login { "username": "admin", "password": "password123" } // 返回 { "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "user": { "id": 1, "username": "admin", "nickname": "管理员", "roles": ["admin"], // 用户的角色列表 "permissions": [ // 用户的所有权限(从角色中聚合) "user:create", "user:read", "user:update", "user:delete", "role:create", "role:read" ] } } ``` ### 2. 访问受保护的接口 ```typescript // 请求头 Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... // 流程 1. JwtAuthGuard 验证 Token └─> 提取用户信息,添加到 req.user 2. RolesGuard 检查角色 └─> 从 req.user.roles 中检查是否包含所需角色 └─> 如果包含,允许访问;否则返回 403 Forbidden ``` ## 🎨 前端权限控制示例 ### Vue 3 中使用权限 ```typescript // stores/auth.ts export const useAuthStore = defineStore('auth', () => { const user = ref(null); // 检查是否有指定角色 const hasRole = (role: string) => { return user.value?.roles?.includes(role) ?? false; }; // 检查是否有指定权限 const hasPermission = (permission: string) => { return user.value?.permissions?.includes(permission) ?? false; }; // 检查是否有任一角色 const hasAnyRole = (roles: string[]) => { return roles.some(role => hasRole(role)); }; // 检查是否有任一权限 const hasAnyPermission = (permissions: string[]) => { return permissions.some(perm => hasPermission(perm)); }; return { user, hasRole, hasPermission, hasAnyRole, hasAnyPermission, }; }); ``` ### 在组件中使用 ```vue ``` ### 路由守卫 ```typescript // router/index.ts router.beforeEach((to, from, next) => { const authStore = useAuthStore(); // 检查是否需要认证 if (to.meta.requiresAuth && !authStore.isAuthenticated) { next({ name: 'Login' }); return; } // 检查角色 if (to.meta.roles && !authStore.hasAnyRole(to.meta.roles)) { next({ name: 'Forbidden' }); return; } // 检查权限 if (to.meta.permissions && !authStore.hasAnyPermission(to.meta.permissions)) { next({ name: 'Forbidden' }); return; } next(); }); ``` ## 📊 权限矩阵示例 | 角色 | user:create | user:read | user:update | user:delete | role:create | role:read | |------|-------------|-----------|-------------|------------|-------------|-----------| | admin | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | editor | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | | viewer | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ## 🎯 总结 RBAC 权限控制的核心是: 1. **用户** ←→ **角色** ←→ **权限** 2. 通过 `@Roles()` 装饰器控制接口访问 3. 前端根据返回的 `roles` 和 `permissions` 控制 UI 显示 4. 权限由 `resource:action` 组成,如 `user:create` 这样的设计既保证了安全性,又提供了良好的灵活性和可维护性!