给特定查询字段添加@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.20go version 1.19
问题原因排查方向
- 代码生成错误:gqlgen可能错误地将
@auth指令应用到了所有Query字段,而非仅activePackages。 - 全局中间件干扰:若gin路由添加了全局token验证中间件,会导致所有请求强制验证token,忽略字段级指令配置。
- 错误处理逻辑异常:自定义的错误拦截器可能将字段级错误转为全局错误,终止整个请求。
- 工具函数影响:
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
相关产品推荐
相关产品推荐

