Skip to content

Guard 守卫只有一个职责。它们根据运行时存在的某些条件(例如权限、角色、ACL 等)决定路由处理程序是否处理给定的请求。这通常被称为授权

在传统的 Express 应用程序中,授权(或者称作身份验证)通常由中间件处理。

中间件是身份验证的理想选择,因为诸如令牌验证和将属性附加到 request 对象之类的操作与特定的路由上下文(及其元数据)并没有紧密的联系。

但中间件本质上是愚蠢的。因为它不知道在调用 next() 函数后会执行哪个处理程序。

Guard 可以访问 ExecutionContext 实例,因此确切知道接下来要执行什么。

它的设计与异常过滤器、管道和拦截器非常相似,旨在请求/响应周期的正确位置插入处理逻辑,并以声明式的方式进行

1.Authorization guard

授权是 Guards 的绝佳用例,因为只有当调用者(通常是特定的经过身份验证的用户)拥有足够的权限时,特定的路由才可用。

每个守卫都必须实现一个 canActivate() 函数。

该函数应返回一个布尔值,指示当前请求是否被允许。它可以同步或异步地(通过 PromiseObservable )返回响应。

Nest 使用返回值来控制下一步操作:

  • 如果返回 true ,则请求将被处理。
  • 如果返回 falseNest 将拒绝该请求。
ts
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);
  }
}

2.Role

ts
// roles.decorator.ts
import { Reflector } from '@nestjs/core';

export const Roles = Reflector.createDecorator<string[]>();
ts
// cats.controller.ts
@Post()
@Roles(['admin'])
async create(@Body() createCatDto: CreateCatDto) {
  this.catsService.create(createCatDto);
}
ts
// roles.guard.ts
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 {
    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);
  }
}