You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS GraphQL中如何为@ResolveField使用@UseGuards装饰器

NestJS GraphQL 字段级权限控制实现方案

需求场景

  • 主查询接口公开可访问,无权限拦截
  • 返回结果中的特定敏感字段仅对指定身份用户可见
  • 约束条件:不新增额外数据查询、不使用字段守卫以外的其他权限控制方式

具体实现

1. 主查询保持公开无守卫

主查询对应的@Query方法不挂载任何权限守卫,仅处理公开数据的查询逻辑,保证匿名/所有用户都能正常请求拿到公开字段数据:

@Resolver(() => Article)
export class ArticleResolver {
  constructor(private articleService: ArticleService) {}

  // 无任何守卫,公开可访问
  @Query(() => Article)
  async article(@Args('id') id: number) {
    return this.articleService.getById(id);
  }
}

2. 敏感字段单独挂载字段级守卫

需要权限控制的字段不要在主查询里直接返回,单独写@ResolveField解析方法,仅在这个方法上挂载@UseGuards,不影响主查询和其他公开字段:

// 同ArticleResolver内补充字段解析逻辑
@ResolveField(() => String, { nullable: true })
@UseGuards(ArticleSensitiveGuard) // 仅敏感字段挂守卫
async sensitiveContent(@Parent() article: Article) {
  // 守卫校验通过才会执行到这里,返回真实敏感内容
  return article.sensitiveContent;
}

3. 自定义守卫适配无额外查询逻辑

守卫内部直接从GraphQL上下文取已解析好的用户信息、父级查询已经返回的实体数据做权限判断,不需要重复查库:

@Injectable()
export class ArticleSensitiveGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const gqlCtx = GqlExecutionContext.create(context);
    const request = gqlCtx.getContext().req;
    const currentUser = request.user; // 取全局身份解析逻辑已经挂在req上的用户信息,无额外查询
    const targetArticle = gqlCtx.getParent<Article>(); // 取主查询已经查出的文章实体,无额外查询

    // 自定义权限规则:仅文章作者、平台管理员可见敏感字段
    return currentUser?.id === targetArticle.authorId || currentUser?.role === 'admin';
  }
}

效果说明

  • 未授权用户请求主查询时,可以正常拿到标题、正文、发布时间等公开字段,sensitiveContent字段自动返回null
  • 符合权限要求的用户请求时,可以拿到完整的所有字段值
  • 整个流程没有新增任何额外数据库查询,仅使用@ResolveField上挂载的守卫完成权限控制,完全匹配需求

注意:记得给敏感字段设置nullable: true,否则未授权时会直接抛权限异常中断整个请求,而不是仅隐藏敏感字段。

内容的提问来源于stack exchange,提问作者johnykes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 02:18:15