跳到主要内容

守卫

创建守卫

守卫有单独的责任。它们根据运行时出现的某些条件(例如权限,角色,访问控制列表等)来确定给定的请求是否由路由处理程序处理。这通常称为授权。在传统的 Express 应用程序中,通常由中间件处理授权(以及认证)。

守卫在中间件后执行

我们在user里创建一个守卫

cd src/user
nest g gu myrole

守卫要求实现函数canActivate,给定参数context执行上下文要求返回布尔值

image-20221123153719088

使用UseGuards控制守卫

user.controller.ts
import {
Controller,
UseGuards,
} from '@nestjs/common';
import { MyroleGuard } from './myrole/myrole.guard';
@UseGuards(MyroleGuard)
@Controller()
XXXXXX

image-20221125105639222

全局守卫

main.ts
import { MyroleGuard } from './user/myrole/myrole.guard';
app.useGlobalGuards(new MyroleGuard());

针对角色控制守卫

@SetMetadata装饰器

第一个参数为key,第二个参数自定义,这里放数组格式来读权限

image-20221126104200383

guard 使用 Reflector反射读取setMetaData的值去做判断,假如从url 判断有没有admin权限

myrole.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
import { Reflector } from '@nestjs/core';
import type { Request } from 'express';

@Injectable()
export class MyroleGuard implements CanActivate {
constructor(private Reflector: Reflector) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const admin = this.Reflector.get<string[]>('myrole', context.getHandler());
const request = context.switchToHttp().getRequest<Request>();
console.log('经过了守卫', admin, request.query);
if (admin?.includes(request?.query?.myrole as string)) {
return true;
} else {
return false;
}
}
}

如果通过

image-20221126104316518

通过失败

image-20221126104418534

注意全局守卫,如果还是使用如下方式就会报错

main.ts
app.useGlobalGuards(new MyroleGuard());

我们需要传入Reflector,issues,即

main.ts
import { MyroleGuard } from './user/myrole/myrole.guard';
import { Reflector } from '@nestjs/core';
app.useGlobalGuards(new MyroleGuard(new Reflector()));