简体   繁体   English

如何解码 Go 中的 JWT 令牌?

[英]How to decode a JWT token in Go?

I am currently working on a Go application.我目前正在处理 Go 应用程序。 I receive a JWT token from the client side and I need to decode that token and obtain the relevant information: user, name, etc.我从客户端收到一个 JWT 令牌,我需要解码该令牌并获取相关信息:用户、姓名等。

I was checking the libraries that are available to handle JWT tokens and I came down to dgrijalva/jwt-go , but I don't see how to accomplish my goal in a simple way.我正在检查可用于处理 JWT 令牌的库,然后我来到了dgrijalva/jwt-go ,但我不知道如何以简单的方式实现我的目标。

I have the token and I need to decode the info into a map or at least a json. How can I do it?我有令牌,我需要将信息解码为 map 或至少为 json。我该怎么做?

I am currently working on a Golang application.I receive a JWT token from the client side and, in Go I need to decode that token and get the information: user, name, etc. I was checking the libraries that are available to handle JWT tokens and I came down to https://github.com/dgrijalva/jwt-go , but I don't see how to simply make what I need.我目前正在开发一个 Golang 应用程序。我从客户端收到一个 JWT 令牌,在 Go 中我需要解码该令牌并获取信息:用户、名称等。我正在检查可用于处理 JWT 的库令牌,我归结为https://github.com/dgrijalva/jwt-go ,但我不知道如何简单地制作我需要的东西。

I have the token and I need to decode the info into a map or at least a json.我有令牌,我需要将信息解码成地图或至少是 json。 Where can I find a guide of how to do it?我在哪里可以找到如何操作的指南? Thank you!谢谢!

I am currently working on a Golang application.I receive a JWT token from the client side and, in Go I need to decode that token and get the information: user, name, etc. I was checking the libraries that are available to handle JWT tokens and I came down to https://github.com/dgrijalva/jwt-go , but I don't see how to simply make what I need.我目前正在开发一个 Golang 应用程序。我从客户端收到一个 JWT 令牌,在 Go 中我需要解码该令牌并获取信息:用户、名称等。我正在检查可用于处理 JWT 的库令牌,我归结为https://github.com/dgrijalva/jwt-go ,但我不知道如何简单地制作我需要的东西。

I have the token and I need to decode the info into a map or at least a json.我有令牌,我需要将信息解码成地图或至少是 json。 Where can I find a guide of how to do it?我在哪里可以找到如何操作的指南? Thank you!谢谢!

Since both the question and answers mention the JWT library github.com/dgrijalva/jwt-go , please note that this library has been unmaintained for a long time now.由于问题和答案都提到了 JWT 库github.com/dgrijalva/jwt-go ,请注意这个库已经很久没有维护了。

As of June 2021 there is a community fork golang-jwt/jwt , officially blessed by Dave Grijalva, the original author.截至 2021 年 6 月,社区分叉golang-jwt/jwt由原作者 Dave Grijalva 正式加持

This also means that the library import path has changed.这也意味着库导入路径发生了变化。 Note that the current major version v3 is not on Go modules, therefore you will still see v3.x.x+incompatible in your go.mod .请注意, 当前 主要版本v3不在 Go 模块上,因此您仍会在go.mod中看到v3.x.x+incompatible


Edit: since August 2021 version v4 of golang-jwt/jwt is available.编辑:自 2021 年 8 月起, golang-jwt/jwtv4版本可用。 This finally supports Go modules .这终于支持 Go modules 了 The new version is backward-compatible with previous versions, so in order to migrate simply replace the old import path with:新版本向后兼容以前的版本,因此为了迁移只需将旧的导入路径替换为:

github.com/golang-jwt/jwt/v4

then update your modules as needed — see also the migration guide for details.然后根据需要更新您的模块 - 另请参阅 迁移指南了解详细信息。


The fork most notably fixes an important security issue with the original library.最值得注意的是,fork 修复了原始库的一个重要安全问题 Before the fix, the library didn't properly handle multiple aud in the JWT claims, making it actually not compliant with the JWT spec.在修复之前,该库没有正确处理 JWT 声明中的多个aud ,使其实际上不符合 JWT 规范。

Apart from that, the main API is still the same.除此之外,主要的 API 还是一样的。 For example to parse a JWT with HMAC verification:例如,使用 HMAC 验证解析 JWT:

    tokenString := /* raw JWT string*/

    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, errors.New("unexpected signing method")
        }
        return []byte(/* your JWT secret*/), nil
    })
    if err != nil {
        // handle err
    }

    // validate the essential claims
    if !token.Valid {
        // handle invalid tokebn
    }

To parse a JWT with custom claims, you can define your own struct type and embed jwt.StandardClaims into it:要使用自定义声明解析 JWT,您可以定义自己的结构类型并将jwt.StandardClaims嵌入其中:

    type MyClaims struct {
        jwt.StandardClaims
        MyField string `json:"my_field"`
    }

    tokenString := /* raw JWT string*/

    // pass your custom claims to the parser function
    token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, errors.New("unexpected signing method")
        }
        return []byte(/* your JWT secret*/), nil
    })

    // type-assert `Claims` into a variable of the appropriate type
    myClaims := token.Claims.(*MyClaims)

A valid alternative to this library is lestrrat-go/jwx .该库的一个有效替代方案是lestrrat-go/jwx The API is slightly different, but also very easy to use: API 略有不同,但也非常易于使用:

    tokenString := /* raw JWT string*/

    // parse and verify signature
    tok, err := jwt.Parse(tokenString, jwt.WithVerify(jwa.HS256, []byte(/* your JWT secret */)))
    if err != nil {
        // handle err
    }

    // validate the essential claims
    if err := jwt.Validate(tok); err != nil {
        // handle err
    }

I am currently working on a Golang application.I receive a JWT token from the client side and, in Go I need to decode that token and get the information: user, name, etc. I was checking the libraries that are available to handle JWT tokens and I came down to https://github.com/dgrijalva/jwt-go , but I don't see how to simply make what I need.我目前正在开发一个 Golang 应用程序。我从客户端收到一个 JWT 令牌,在 Go 中我需要解码该令牌并获取信息:用户、名称等。我正在检查可用于处理 JWT 的库令牌,我归结为https://github.com/dgrijalva/jwt-go ,但我不知道如何简单地制作我需要的东西。

I have the token and I need to decode the info into a map or at least a json.我有令牌,我需要将信息解码成地图或至少是 json。 Where can I find a guide of how to do it?我在哪里可以找到如何操作的指南? Thank you!谢谢!

I am currently working on a Golang application.I receive a JWT token from the client side and, in Go I need to decode that token and get the information: user, name, etc. I was checking the libraries that are available to handle JWT tokens and I came down to https://github.com/dgrijalva/jwt-go , but I don't see how to simply make what I need.我目前正在开发一个 Golang 应用程序。我从客户端收到一个 JWT 令牌,在 Go 中我需要解码该令牌并获取信息:用户、名称等。我正在检查可用于处理 JWT 的库令牌,我归结为https://github.com/dgrijalva/jwt-go ,但我不知道如何简单地制作我需要的东西。

I have the token and I need to decode the info into a map or at least a json.我有令牌,我需要将信息解码成地图或至少是 json。 Where can I find a guide of how to do it?我在哪里可以找到如何操作的指南? Thank you!谢谢!

I had a kind of very similar use case where I wanted to verify an access token and extract fields(such as: iss , sub , aud , exp , iat , jti , etc..) from it after decoding.我有一种非常相似的用例,我想在解码后验证访问令牌并从中提取字段(例如: isssubaudexpiatjti等)。 For my use case, I have used jwx and jwt-go libs.对于我的用例,我使用了 jwxjwt-go库。

Please find the detailed code snippet here which worked for me.请在此处找到对我有用的详细代码片段。

Code snippet代码片段

go.mod去.mod
module my-go-module

go 1.16

require (
    github.com/dgrijalva/jwt-go v3.2.0+incompatible
    github.com/lestrrat-go/jwx v1.0.4
)
main package主包
package main

import (
    "errors"
    "fmt"

    "github.com/dgrijalva/jwt-go"
    "github.com/lestrrat-go/jwx/jwa"
    "github.com/lestrrat-go/jwx/jwk"
)

func main() {
    jwksURL := "https://your-tenant.auth0.com/.well-known/jwks.json"

    keySet, _ := jwk.Fetch(jwksURL)
    var accessToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6Ind5TXdLNEE2Q0w5UXcxMXVvZlZleVExMTlYeVgteHlreW1ra1h5Z1o1T00ifQ.eyJzdWIiOiIwMHUxOGVlaHUzNDlhUzJ5WDFkOCIsIm5hbWUiOiJva3RhcHJveHkgb2t0YXByb3h5IiwidmVyIjoxLCJpc3MiOiJodHRwczovL2NvbXBhbnl4Lm9rdGEuY29tIiwiYXVkIjoidlpWNkNwOHJuNWx4ck45YVo2ODgiLCJpYXQiOjE0ODEzODg0NTMsImV4cCI6MTQ4MTM5MjA1MywianRpIjoiSUQuWm9QdVdIR3IxNkR6a3RUbEdXMFI4b1lRaUhnVWg0aUotTHo3Z3BGcGItUSIsImFtciI6WyJwd2QiXSwiaWRwIjoiMDBveTc0YzBnd0hOWE1SSkJGUkkiLCJub25jZSI6Im4tMFM2X1d6QTJNaiIsInByZWZlcnJlZF91c2VybmFtZSI6Im9rdGFwcm94eUBva3RhLmNvbSIsImF1dGhfdGltZSI6MTQ4MTM4ODQ0MywiYXRfaGFzaCI6Im1YWlQtZjJJczhOQklIcV9CeE1ISFEifQ.OtVyCK0sE6Cuclg9VMD2AwLhqEyq2nv3a1bfxlzeS-bdu9KtYxcPSxJ6vxMcSSbMIIq9eEz9JFMU80zqgDPHBCjlOsC5SIPz7mm1Z3gCwq4zsFJ-2NIzYxA3p161ZRsPv_3bUyg9B_DPFyBoihgwWm6yrvrb4rmHXrDkjxpxCLPp3OeIpc_kb2t8r5HEQ5UBZPrsiScvuoVW13YwWpze59qBl_84n9xdmQ5pS7DklzkAVgqJT_NWBlb5uo6eW26HtJwHzss7xOIdQtcOtC1Gj3O82a55VJSQnsEEBeqG1ESb5Haq_hJgxYQnBssKydPCIxdZiye-0Ll9L8wWwpzwig"
    token, err := verify(accessToken, keySet)
    if err != nil {
        fmt.Printf("Gor an error while verifiying access token: %v\n", err)
    }

    // Check if the token is valid.
    if !token.Valid {
        fmt.Println("The token is not valid.")
    }

    // Extract key value from the token and print them on console
    claims := token.Claims.(jwt.MapClaims)
    for key, value := range claims {
        fmt.Printf("%s\t%v\n", key, value)
    }
}

func verify(tokenString string, keySet *jwk.Set) (*jwt.Token, error) {
    tkn, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        if token.Method.Alg() != jwa.RS256.String() { 
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }
        kid, ok := token.Header["kid"].(string)
        if !ok {
            return nil, errors.New("kid header not found")
        }
        keys := keySet.LookupKeyID(kid)
        if len(keys) == 0 {
            return nil, fmt.Errorf("key %v not found", kid)
        }
        var raw interface{}
        return raw, keys[0].Raw(&raw)
    })
    return tkn, err
}

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

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