Guard
守卫只有一个职责。它们根据运行时存在的某些条件(例如权限、角色、ACL 等)决定路由处理程序是否处理给定的请求。这通常被称为授权。
在传统的 Express
应用程序中,授权(或者称作身份验证)通常由中间件处理。
中间件是身份验证的理想选择,因为诸如令牌验证和将属性附加到 request
对象之类的操作与特定的路由上下文(及其元数据)并没有紧密的联系。
但中间件本质上是愚蠢的。因为它不知道在调用 next()
函数后会执行哪个处理程序。
而 Guard
可以访问 ExecutionContext
实例,因此确切知道接下来要执行什么。
它的设计与异常过滤器、管道和拦截器非常相似,旨在请求/响应周期的正确位置插入处理逻辑,并以声明式的方式进行。
1.Authorization guard
授权是 Guards
的绝佳用例,因为只有当调用者(通常是特定的经过身份验证的用户)拥有足够的权限时,特定的路由才可用。
每个守卫都必须实现一个 canActivate()
函数。
该函数应返回一个布尔值,指示当前请求是否被允许。它可以同步或异步地(通过 Promise
或 Observable
)返回响应。
Nest
使用返回值来控制下一步操作:
- 如果返回
true
,则请求将被处理。 - 如果返回
false
,Nest
将拒绝该请求。
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);
}
}