NestJS GraphQL自定义验证器中如何获取上下文用户信息
在GraphQL自定义验证器中获取当前用户的方案
要在Class Validator的自定义验证器里拿到当前用户,核心是通过ValidationArguments获取Nest的执行上下文,再转换为GraphQL上下文提取用户信息,以下是两种可行实现方式:
方式一:通过验证器参数传递上下文
1. 实现自定义验证器
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator'; import { GqlExecutionContext, ExecutionContext } from '@nestjs/graphql'; @ValidatorConstraint({ name: 'userPermissionValidator', async: false }) export class UserPermissionValidator implements ValidatorConstraintInterface { validate(value: any, args: ValidationArguments) { // 从验证参数中获取传入的执行上下文 const ctx = args.constraints[0] as ExecutionContext; // 转换为GraphQL专属上下文 const gqlCtx = GqlExecutionContext.create(ctx); // 提取用户(逻辑和你自定义的CurrentUser装饰器一致) const user = gqlCtx.getContext().req.user; // 示例验证逻辑:仅拥有指定权限的用户可通过 if (!user || !user.permissions.includes('edit_resource')) { return false; } return true; } defaultMessage(args: ValidationArguments) { return '你没有权限执行此操作'; } }
2. 在GraphQL输入DTO中使用验证器
在输入类型里通过@Validate装饰器,将ExecutionContext作为参数传入验证器:
import { InputType, Field } from '@nestjs/graphql'; import { Validate } from 'class-validator'; import { UserPermissionValidator } from './user-permission.validator'; import { ExecutionContext } from '@nestjs/common'; @InputType() export class UpdateResourceInput { @Field() resourceId: string; @Field() @Validate(UserPermissionValidator, [ExecutionContext]) newName: string; }
方式二:依赖注入获取上下文(无需传参)
如果不想每次使用验证器都传递上下文,可以通过依赖注入ExecutionHost来自动获取:
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator'; import { GqlExecutionContext } from '@nestjs/graphql'; import { ExecutionHost, Injectable } from '@nestjs/common'; @ValidatorConstraint({ name: 'userPermissionValidator', async: false }) @Injectable() export class UserPermissionValidator implements ValidatorConstraintInterface { constructor(private readonly executionHost: ExecutionHost) {} validate(value: any, args: ValidationArguments) { // 通过注入的ExecutionHost获取上下文并转换 const gqlCtx = GqlExecutionContext.create(this.executionHost); const user = gqlCtx.getContext().req.user; // 验证逻辑同上 if (!user || !user.permissions.includes('edit_resource')) { return false; } return true; } defaultMessage(args: ValidationArguments) { return '你没有权限执行此操作'; } }
注意:这种方式需要将验证器添加到对应模块的providers数组中,确保Nest可以完成依赖注入。
内容的提问来源于stack exchange,提问作者Juan Chaves
相关产品推荐
相关产品推荐

