NestJs 守卫

简介

https://docs.nestjs.cn/9/guards

守卫是一个使用 @Injectable() 装饰器的类。 守卫应该实现 CanActivate 接口。

img

守卫有一个单独的责任。它们根据运行时出现的某些条件(例如权限,角色,访问控制列表等)来确定给定的请求是否由路由处理程序处理。这通常称为授权。在传统的 Express 应用程序中,通常由中间件处理授权(以及认证)。中间件是身份验证的良好选择,因为诸如 token 验证或添加属性到 request 对象上与特定路由(及其元数据)没有强关联。

中间件不知道调用 next() 函数后会执行哪个处理程序。另一方面,守卫可以访问 ExecutionContext 实例,因此确切地知道接下来要执行什么。它们的设计与异常过滤器、管道和拦截器非常相似,目的是让您在请求/响应周期的正确位置插入处理逻辑,并以声明的方式进行插入。这有助于保持代码的简洁和声明性。

守卫在每个中间件之后执行,但在任何拦截器或管道之前执行。

创建一个守卫

nest g gu [name]

例:
nest g gu role

注意:上面的命令在那个目录下执行,就会在那个目录下创建

image-20230407095153902

内容

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

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;
  }
}

image-20230407095326745

Controller 使用守卫

我们在守卫中打印一句

console.log('假设已经通过了守卫规则的校验。。。。。。。。')

image-20230407095637140

在 p 模块中使用

主要代码

import { RoleGuard } from '../common/role/role.guard';
@UseGuards(RoleGuard)

image-20230407100052933

测试

http://localhost:3000/p/7f145099-e9c7-47d9-99fb-a0a3f9a39bd7?id=1314

image-20230407100427752

全局守卫

如果要注册全局守卫,只需要在 main.ts 中注册即可

创建守卫

nest g gu global

image-20230407100838570

守卫内容

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';

@Injectable()
export class GlobalGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    console.log('这里是全局守卫。。。。。。。。。');
    return true;
  }
}

main.ts 中注册

// 注册全局守卫
app.useGlobalGuards(new GlobalGuard)

image-20230407101103283

测试结果

image-20230407101148462

针对角色控制守卫

注意这里只能装饰 controller 的方法,不能全局

SetMetadata 装饰器

第一个参数为key,第二个参数自定义我们的例子是数组存放的权限

controller 中使用

@SetMetadata('role', ['admin'])

image-20230407105051154

角色守卫内容

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> {
    // guard  使用  Reflector 反射读取 setMetaData的值 
    const admin = this.Reflector.get<string[]>('role', context.getHandler())
    const request = context.switchToHttp().getRequest<Request>()
    // 去做判断这边例子是从url 判断有没有admin权限
    if (admin.includes(request.query.role as string)) {
      console.log('返回true');
      return true;
    }else{
      console.log('返回false');
      return false
    }

  }
}

image-20230407105327000

测试

正确的

http://localhost:3000/p?role=admin

image-20230407105419368

错误的

http://localhost:3000/p?role=test

image-20230407105513885

posted @ 2023-04-07 10:55  makalo  阅读(127)  评论(0编辑  收藏  举报