守卫是一个用 @Injectable() 装饰器注释的类,它实现了 CanActivate 接口。
守卫在 controller 之前执行,它的职责是单一的。它根据运行时的某些条件判断是否将请求交给路由程序处理。
canActivate 函数接收一个 context 参数,它的类型是 ExecutionContext。它扩展了 ArgumentsHost 类型。canActivate 函数的返回值为布尔类型(同步 boolean、异步 Promise<boolean>)。当返回 true,请求会被处理,返回 false 请求将会被拒绝。
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const request = context.switchToHttp().getRequest();
return validateRequest(request);
}
}
守卫传惨
守卫可以通过自定义元数据传递参数。通过内置 Reflector 类创建装饰器,并注入数据,然后在守卫中获取对应数据处理。
import { Reflector } from '@nestjs/core';
export const Roles = Reflector.createDecorator<string[]>();
@Post()
@Roles(['admin'])
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Roles } from './roles.decorator';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
// getHandler 函数获取当前请求所对应的处理器,即被调用的控制器方法。
const roles = this.reflector.get(Roles, context.getHandler());
if (!roles) {
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
return matchRoles(roles, user.roles);
}
}