简体   繁体   English

GraphQL Golang 身份验证与 JWT

[英]GraphQL Golang Authentication with JWT

I have a GraphQL API that I've been writing in go and wondering how to manage JWT authentication when you already are using context to pass around data sources. I have a GraphQL API that I've been writing in go and wondering how to manage JWT authentication when you already are using context to pass around data sources.

So an abbreviated version of my main function is:所以我的main function 的缩写版本是:

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)))
}

As you can see, I'm already creating a new context instance to store and pass a map of my various data sources to the query resolution functions, but also need to be able to parse out the Authorization header for a possible JWT to be passed down for authenticated routes.如您所见,我已经创建了一个新的context实例来存储并将我的各种数据源的 map 传递给查询解析函数,但还需要能够解析出Authorization header 以将可能的 Z1D1FADBD9150349EEDZF 传递给 8150349EEDZF7 down 用于经过身份验证的路由。

What's the best way to go about this given my current situation?鉴于我目前的情况,go 的最佳方法是什么? (Combine the JWT with the data sources context? Handle data sources differently to free up context ?) (将 JWT 与数据源上下文相结合?以不同方式处理数据源以释放context ?)

A common way of dealing with such authentication headers is to use a middleware to deal with authentication, and add the authentication info to the current context.处理此类身份验证标头的常用方法是使用中间件来处理身份验证,并将身份验证信息添加到当前上下文中。

Currently, you're creating a new context.目前,您正在创建一个新的上下文。 I suggest using the existing HTTP context and adding to that, so you can chain things:我建议使用现有的 HTTP 上下文并添加到其中,这样您就可以链接:

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

And you can install a middleware that does the same:您可以安装一个执行相同操作的中间件:

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)
  }
}

This way, you can check if the context has authentication info, and if so, use it.这样,您可以检查上下文是否具有身份验证信息,如果有,请使用它。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM