守卫
守卫根据运行时出现的某些条件(例如权限,角色,访问控制列表等)来确定给定的请求是否由路由处理程序处理,这通常称为授权
在传统的Express应用程序中,通常由中间件处理授权(以及认证);中间件是身份验证的良好选择,因为诸如token验证或添加属性到request对象上与特定路由(及其元数据)没有强关联
守卫在每个中间件之后执行,在任何拦截器或管道之前执行
执行顺序:中间件→守卫→拦截器→管道
使用守卫
创建一个守卫:
创建后:
1 2 3 4 5 6 7 8 9 10 11
| import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Observable } from 'rxjs';
@Injectable() export class RoleGuard implements CanActivate { canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> { return true; } }
|
Controller使用守卫
使用@UseGuards应用守卫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import { Controller, Get, UseGuards, } from '@nestjs/common'; import { GuardService } from './guard.service'; import { RoleGuard } from './role/role.guard';
@Controller('guard')
@UseGuards(RoleGuard) export class GuardController { constructor(private readonly guardService: GuardService) {} @Get() findAll() { return this.guardService.findAll(); } }
|
全局守卫
在main.ts中注册全局守卫
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import { NestFactory } from '@nestjs/core'; import { VersioningType } from '@nestjs/common'; import { AppModule } from './app.module'; import { NestExpressApplication } from '@nestjs/platform-express'; import { RoleGuard } from './guard/role/role.guard';
async function bootstrap() { const app = await NestFactory.create<NestExpressApplication>(AppModule, { cors: true, }); app.enableVersioning({ type: VersioningType.URI, }); app.useGlobalGuards(new RoleGuard()); await app.listen(3000); } bootstrap();
|
针对角色控制守卫
在Controller定义元信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import { Controller, Get, UseGuards, SetMetadata, } from '@nestjs/common'; import { GuardService } from './guard.service'; import { RoleGuard } from './role/role.guard';
@Controller('guard') @UseGuards(RoleGuard) export class GuardController { constructor(private readonly guardService: GuardService) {} @Get() @SetMetadata('role', ['admin']) findAll() { return this.guardService.findAll(); } }
|
在守卫安排判断逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common'; import { Observable } from 'rxjs'; import { Reflector } from '@nestjs/core'; import type { Request } from 'express';
@Injectable() export class RoleGuard implements CanActivate { constructor(private Reflector: Reflector) {}
canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> { const admin = this.Reflector.get<string[]>('role', context.getHandler()); const req = context.switchToHttp().getRequest<Request>(); const role = req.query.role; if (admin.includes(role as string)) { return true; } else { return false; } } }
|
角色不符合权限:
角色符合权限: