Guards 决定了一个请求是否被允许进行到路由处理程序 — 它们是 NestJS 专门为授权(通常还包括身份验证检查)设计的机制。Guard 返回 true 以允许请求,或返回 false/抛出异常以阻止请求。
基础的 guard
ts
()
{
(: ): {
request = context.().();
!!request..;
}
}
Guard 实现 canActivate() 方法,返回一个布尔值(或其 Promise/Observable)。返回 false 会用 403 阻止请求;你也可以抛出特定异常(例如 UnauthorizedException)。
@UseGuards(AuthGuard) // on a single route
@Get("profile")
getProfile() {}
@UseGuards(AuthGuard) // on a whole controller (all routes)
@Controller("admin")
export class AdminController {}
app.useGlobalGuards(new AuthGuard()); // globally (all routes)
Guards 可以在方法、控制器或全局级别应用。
@Injectable()
export class JwtAuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = request.headers.authorization?.split(" ")[1];
if (!token) throw new UnauthorizedException();
try {
request.user = await this.jwtService.verifyAsync(token); // attach the user
return true;
} catch {
throw new UnauthorizedException("Invalid token");
}
}
}
// a @Roles decorator stores required roles as metadata
@Roles("admin")
@Get("users")
listUsers() {}
// the RolesGuard reads the metadata and checks the user's roles
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(ctx: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>("roles", ctx.getHandler());
const { user } = ctx.switchToHttp().getRequest();
return roles.some(role => user.roles?.includes(role)); // allow if the user has a required role
}
}
将 @Roles() 装饰器(元数据)与读取它的 guard(通过 Reflector)相结合是基于角色的访问控制的标准模式。
The ExecutionContext gives guards rich info (the handler, class, request) — more
than plain middleware — which is why guards (not middleware) are the right place
for authorization decisions.
Guards 是 NestJS 中专门的、惯用的授权机制 — 根据身份验证和权限来控制允许哪些请求到达处理程序。
理解它们至关重要,因为几乎每个真实的应用程序都需要保护路由(要求登录、检查角色/权限),而 guards 是完成这项工作的正确工具(比将身份验证逻辑塞入中间件或每个处理程序中要简洁得多)。
标准模式 — 验证凭据并将用户附加到请求的 JWT/auth guard,以及基于角色的 guards,它将 @Roles() 装饰器与读取 Reflector 的 guard 结合使用以实现 RBAC — 是保护 NestJS API 的基础。
Guards 对丰富的 ExecutionContext 的访问(了解目标处理程序、类和请求)正是使它们适合于授权决策的原因,而中间件无法干净地做出这些决策。
了解如何编写、应用(方法/控制器/全局)和将 guards 与元数据装饰器组合是构建安全的 NestJS 应用程序的核心知识,也是该框架中频繁出现的、在架构上很重要的主题。