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

给特定查询字段添加@auth指令后,单查询失效致所有查询不可用的问题

问题:@auth指令验证失败导致所有查询失效

我给Query类型的activePackages查询字段添加了@auth指令,但发现当该查询的指令验证失败时,所有查询都无法正常执行,与预期不符。预期效果为:仅添加了@auth指令的查询受该指令影响,其他查询可正常执行。


复现用最小代码

GraphQL Schema

directive @auth on FIELD_DEFINITION

type Data {
    code: Int!     
    status: String!  
    message: String!   
    packages: [String!]!
}

type PackageData {
    code: Int!     
    status: String!  
    message: String!   
    package: String!
}

type Query {
  completedPackages(limit: Int!, page: Int!): Data!
  getPackage(id: ID!): PackageData!
  activePackages(limit: Int!, page: Int!): Data! @auth
}

Go 代码实现

func Auth(ctx context.Context, obj interface{}, next graphql.Resolver) (interface{}, error) {
    tokenData, err := middleware.CtxValue(ctx)
    if err != nil {
        return nil, err
    }
    if tokenData == nil {
        return nil, &gqlerror.Error{
            Message: "Access Denied",
        }
    }

    return next(ctx)
}

func GraphqlHandler(db *mongo.Database) gin.HandlerFunc {
    // NewExecutableSchema and Config are in the generated.go file
    // Resolver is in the resolver.go file
    c := generated.Config{Resolvers: &graph.Resolver{Collection: db.Collection("deliveries")}}
    c.Directives.Auth = directives.Auth
    h := handler.NewDefaultServer(
        generated.NewExecutableSchema(c))

    return func(c *gin.Context) {
        h.ServeHTTP(c.Writer, c.Request)
    }
}

使用版本

  • go run github.com/99designs/gqlgen 0.17.20
  • go version 1.19

问题原因排查方向

  1. 代码生成错误:gqlgen可能错误地将@auth指令应用到了所有Query字段,而非仅activePackages。
  2. 全局中间件干扰:若gin路由添加了全局token验证中间件,会导致所有请求强制验证token,忽略字段级指令配置。
  3. 错误处理逻辑异常:自定义的错误拦截器可能将字段级错误转为全局错误,终止整个请求。
  4. 工具函数影响:middleware.CtxValue的实现可能在验证失败时修改了请求上下文,影响后续查询执行。

解决方案

1. 重新生成代码确保指令应用正确

执行gqlgen生成命令,更新自动生成的代码:

go run github.com/99designs/gqlgen generate

检查生成的generated.go文件,确认仅activePackages的resolver被Auth指令包裹,其他查询字段的resolver无相关逻辑。

2. 移除全局Auth中间件

检查gin路由配置,若存在全局token验证中间件(如r.Use(middleware.AuthMiddleware())),直接移除,仅保留字段级@auth指令控制权限。

3. 验证部分响应功能

对于包含多个查询字段的请求(如下示例),测试token无效时的响应:

query {
  completedPackages(limit: 10, page: 1) {
    code
    status
  }
  activePackages(limit: 10, page: 1) {
    code
    status
  }
}

正常响应应包含completedPackages的有效数据,同时errors数组中返回activePackages的"Access Denied"错误。若未达到此效果,检查是否自定义了handler的错误处理逻辑,确保使用handler.NewDefaultServer的默认配置。

4. 修正middleware.CtxValue实现

确保该函数仅在Auth指令中被调用,且仅返回token数据或错误,不修改全局上下文。示例实现:

func CtxValue(ctx context.Context) (interface{}, error) {
    // 尝试从gin上下文获取请求头
    ginCtx, ok := ctx.Value(gin.ContextKey).(*gin.Context)
    if !ok {
        return nil, errors.New("无法获取请求上下文")
    }
    authHeader := ginCtx.GetHeader("Authorization")
    if authHeader == "" {
        return nil, nil
    }
    // 此处添加token解析逻辑
    parsedToken, err := parseToken(authHeader)
    if err != nil {
        return nil, err
    }
    return parsedToken, nil
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:55:42