Go -- JWT

jwt-go 是一个用于处理 JSON Web Tokens (JWT) 的 Go 语言库。它支持多种算法,如 HS256、RS256 等。以下是如何在 Go 语言项目中使用 jwt-go 的基本步骤:

安装 jwt-go

首先,需要安装 jwt-go 包。可以使用以下命令:

go get -u github.com/dgrijalva/jwt-go

生成 JWT

生成 JWT 时,需要定义一个 Token 结构,并使用相应的密钥进行签名。

package main

import (
    "fmt"
    "time"

    "github.com/dgrijalva/jwt-go"
)

func main() {
    // 定义JWT的签发者和接收者
    issuer := "example.com"
    audience := "api.example.com"

    // 定义JWT的过期时间
    expirationTime := time.Now().Add(24 * time.Hour)

    // 创建一个JWT的Token对象
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
        "iss":   issuer,   // 签发者
        "aud":   audience, // 接收者
        "iat":   time.Now().Unix(), // 发布时间
        "nbf":   time.Now().Unix(), // 在此之前不可用
        "exp":   expirationTime.Unix(), // 过期时间
        "custom": "data", // 自定义数据
    })

    // 使用密钥进行签名
    key := []byte("secret")
    signedToken, err := token.SignedString(key)
    if err != nil {
        fmt.Println("Token signing error:", err)
        return
    }

    fmt.Println("Signed Token:", signedToken)
}

验证 JWT

验证 JWT 时,需要使用相同的密钥和算法来验证签名。

package main

import (
    "fmt"
    "time"

    "github.com/dgrijalva/jwt-go"
)

func main() {
    token := "你的JWT字符串" // 从上一步生成的JWT字符串

    // 解析JWT字符串
    tokenObj, err := jwt.Parse(token, func(token *jwt.Token) (interface{}, error) {
        // 确保算法是HS256
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }

        // 返回用于验证签名的密钥
        return []byte("secret"), nil
    })

    if err != nil {
        fmt.Println("Token parsing error:", err)
        return
    }

    // 检查Token是否有效
    if claims, ok := tokenObj.Claims.(jwt.MapClaims); ok && tokenObj.Valid {
        fmt.Println("Token is valid!")
        fmt.Println("Issuer:", claims["iss"])
        fmt.Println("Audience:", claims["aud"])
        fmt.Println("Expiration Time:", time.Unix(int64(claims["exp"].(float64)), 0))
    } else {
        fmt.Println("Token is not valid!")
    }
}

使用 RS256 算法

如果你需要使用 RS256 算法,需要生成 RSA 密钥对,并使用私钥签名,公钥验证。

package main

import (
    "crypto/rand"
    "crypto/rsa"
    "crypto/x509"
    "encoding/pem"
    "fmt"
    "os"

    "github.com/dgrijalva/jwt-go"
)

func main() {
    // 生成RSA密钥对
    privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
    if err != nil {
        fmt.Println("Error generating RSA key:", err)
        return
    }

    // 将私钥写入文件
    privateKeyPem := x509.MarshalPKCS1PrivateKey(privateKey)
    err = os.WriteFile("private.pem", privateKeyPem, 0600)
    if err != nil {
        fmt.Println("Error writing private key to file:", err)
        return
    }

    // 使用私钥生成JWT
    token := jwt.NewWithClaims(jwt.SigningMethodRS256, jwt.MapClaims{
        "iss": "example.com",
        "aud": "api.example.com",
        "iat": time.Now().Unix(),
        "exp": time.Now().Add(24 * time.Hour).Unix(),
    })

    signer, err := jwt.NewRSASigner(privateKey)
    if err != nil {
        fmt.Println("Error creating RSA signer:", err)
        return
    }

    signedToken, err := token.SignedString(signer)
    if err != nil {
        fmt.Println("Error signing token:", err)
        return
    }

    fmt.Println("Signed Token:", signedToken)

    // 读取公钥
    publicKeyBytes, err := os.ReadFile("public.pem")
    if err != nil {
        fmt.Println("Error reading public key file:", err)
        return
    }

    publicKey, err := jwt.ParseRSAPublicKeyFromPEM(publicKeyBytes)
    if err != nil {
        fmt.Println("Error parsing public key:", err)
        return
    }

    // 验证JWT
    tokenObj, err := jwt.Parse(signedToken, func(token *jwt.Token) (interface{}, error) {
        return publicKey, nil
    })

    if err != nil {
        fmt.Println("Error parsing token:", err)
        return
    }

    if claims, ok := tokenObj.Claims.(jwt.MapClaims); ok && tokenObj.Valid {
        fmt.Println("Token is valid!")
        fmt.Println("Issuer:", claims["iss"])
        fmt.Println("Audience:", claims["aud"])
    } else {
        fmt.Println("Token is not valid!")
    }
}

在实际应用中,你可能需要根据具体需求调整 JWT 的内容和验证逻辑。jwt-go 提供了灵活的接口来满足不同的需求。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容