【问题标题】:GraphQL Golang Authentication with JWT使用 JWT 的 GraphQL Golang 身份验证
【发布时间】:2020-04-07 01:25:33
【问题描述】:

我有一个 GraphQL API,我一直在用 go 编写,想知道当您已经在使用 context 传递数据源时如何管理 JWT 身份验证。

所以我的main 函数的缩写版本是:

import (
    "net/http"
    "github.com/graphql-go/graphql"
    gqlhandler "github.com/graphql-go/handler"
)

func queryHandler(ds *sources.DataSources, gql *gqlhandler.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ctx := context.WithValue(context.Background(), sources.CtxSourcesKey, ds)
        gql.ContextHandler(ctx, w, r)
    })
}

func main() {
    apiSchema, _ := schema.CompileSchema(schema.QueryType, schema.MutationType)
    gql := gqlhandler.New(&gqlhandler.Config{
        Schema:     &apiSchema,
        GraphiQL:   !isDeployed,
        Pretty:     false,
        Playground: false,
    })
    http.ListenAndServe(":41000", util.CreateChiRouter(healthCheckHandler(), queryHandler(ctxSources, gql)))
}

如您所见,我已经创建了一个新的context 实例来存储我的各种数据源的映射并将其传递给查询解析函数,但还需要能够解析出Authorization 标头为经过身份验证的路由传递可能的 JWT。

考虑到我目前的情况,最好的解决方法是什么? (将 JWT 与数据源上下文相结合?以不同方式处理数据源以释放 context?)

【问题讨论】:

    标签: go authentication graphql jwt


    【解决方案1】:

    处理此类身份验证标头的常用方法是使用中间件来处理身份验证,并将身份验证信息添加到当前上下文中。

    目前,您正在创建一个新的上下文。我建议使用现有的 HTTP 上下文并添加到其中,这样您就可以链接事物:

    ctx := context.WithValue(r.Context(), sources.CtxSourcesKey, ds)
    newReq:=r.WithContext(ctx)
    gql.ContextHandler(ctx, w, newReq)
    

    你可以安装一个做同样事情的中间件:

    type autoInfoKeyType int
    
    const authInfoKey authInfoKeyType=iota
    
    func GetAuthInfo(ctx context.Context) *AuthInfo {
       if v:=ctx.Value(authInfoKey); v!=nil {
         return v.(*AuthInfo)
       }
       return nil
    }
    
    func AuthMiddleware(next http.Handler) http.Handler {
      return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        authInfo:=processJWT(...)
        if authInfo!=nil {
           ctx := context.WithValue(r.Context(), authInfoKey, authInfo)
           r=r.WithContext(ctx)
        }
        next.ServeHTTP(w,r)
      }
    }
    

    这样,你可以检查上下文是否有认证信息,如果有,使用它。

    if authInfo:=GetAuthInfo(req.Context()); authInfo!=nil {
      ...
    }
    

    【讨论】:

    • 从您的第一个 sn-p 开始,传入请求上下文添加的键是什么? (即它是如何访问的?)
    • 你说的是authInfoKey吗? sources.CtxSourcesKey 来自您的问题
    • 是的,抱歉,不是很清楚。 authInfoKey 的值从何而来?
    • 哦,没关系,我被误读了。那么这是将两个上下文组合成一个要传递的上下文吗?
    • 添加了更多代码以显示 authInfoKey 的实现。这会一直使用 HTTP 请求中的上下文,它不会创建新的上下文。
    猜你喜欢
    • 2018-03-17
    • 2021-03-07
    • 2016-12-17
    • 2018-11-10
    • 2020-06-26
    • 2021-07-31
    • 2021-12-09
    • 2016-04-07
    • 1970-01-01
    相关资源
    最近更新 更多