程序员求职经验分享与学习资料整理平台

网站首页 > 文章精选 正文

Golang 如何使用JWT

balukai 2025-03-10 12:28:10 文章精选 68 ℃

JWT(JSON Web Token) 是一种用于在客户端和服务器之间安全传递信息的开放标准(RFC 7519)。在 Go 语言中,可以通过使用第三方库(如 github.com/golang-jwt/jwt)轻松实现 JWT 的生成和验证。

以下是 Go 语言中使用 JWT 的详细教程,包含代码示例和说明。


1. 安装依赖

首先,安装 Go 的 JWT 库:

go get -u github.com/golang-jwt/jwt/v5

2. 生成 JWT

步骤

  1. 创建一个 JWT 实例。
  2. 设置 JWT 的声明(Claims)。
  3. 使用密钥对 JWT 进行签名。

示例

package main

import (
    "fmt"
    "time"

    "github.com/golang-jwt/jwt/v5"
)

func generateJWT(userID string, secretKey []byte) (string, error) {
    // 1. 创建 JWT 实例
    token := jwt.New(jwt.SigningMethodHS256)

    // 2. 设置 JWT 的声明(Claims)
    claims := token.Claims.(jwt.MapClaims)
    claims["user_id"] = userID
    claims["exp"] = time.Now().Add(time.Hour * 24).Unix() // 设置过期时间为 24 小时后

    // 3. 使用密钥对 JWT 进行签名
    tokenString, err := token.SignedString(secretKey)
    if err != nil {
        return "", err
    }

    return tokenString, nil
}

func main() {
    secretKey := []byte("your-256-bit-secret") // 密钥
    userID := "12345" // 用户 ID

    token, err := generateJWT(userID, secretKey)
    if err != nil {
        fmt.Println("Error generating JWT:", err)
        return
    }

    fmt.Println("Generated JWT:", token)
}

3. 验证 JWT

步骤

  1. 解析 JWT 字符串。
  2. 验证 JWT 的签名和声明。
  3. 获取声明中的数据。

示例

func verifyJWT(tokenString string, secretKey []byte) (jwt.MapClaims, error) {
    // 1. 解析 JWT 字符串
    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        // 验证签名方法
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }
        return secretKey, nil
    })

    // 2. 验证 JWT 的签名和声明
    if err != nil {
        return nil, err
    }

    if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
        return claims, nil
    }

    return nil, fmt.Errorf("invalid token")
}

func main() {
    tokenString := "your.jwt.token.here" // 替换为生成的 JWT

    claims, err := verifyJWT(tokenString, []byte("your-256-bit-secret"))
    if err != nil {
        fmt.Println("Error verifying JWT:", err)
        return
    }

    fmt.Println("User ID:", claims["user_id"]) // 输出:User ID: 12345
}

4. 使用自定义 Claims

如果你需要更复杂的声明,可以定义自己的 Claims 结构。

示例

type CustomClaims struct {
    UserID string `json:"user_id"`
    jwt.RegisteredClaims
}

func generateCustomJWT(userID string, secretKey []byte) (string, error) {
    // 1. 创建自定义声明
    claims := CustomClaims{
        UserID: userID,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)), // 过期时间
            IssuedAt:  jwt.NewNumericDate(time.Now()),                     // 签发时间
        },
    }

    // 2. 创建 JWT 实例
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

    // 3. 使用密钥对 JWT 进行签名
    tokenString, err := token.SignedString(secretKey)
    if err != nil {
        return "", err
    }

    return tokenString, nil
}

5. 生成和验证 JWT 的完整示例

结合上述代码,以下是一个完整的示例:

package main

import (
    "fmt"
    "time"

    "github.com/golang-jwt/jwt/v5"
)

type CustomClaims struct {
    UserID string `json:"user_id"`
    jwt.RegisteredClaims
}

func generateJWT(userID string, secretKey []byte) (string, error) {
    claims := CustomClaims{
        UserID: userID,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)),
        },
    }

    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
    tokenString, err := token.SignedString(secretKey)
    if err != nil {
        return "", err
    }

    return tokenString, nil
}

func verifyJWT(tokenString string, secretKey []byte) (*CustomClaims, error) {
    token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
        }
        return secretKey, nil
    })

    if err != nil {
        return nil, err
    }

    if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
        return claims, nil
    }

    return nil, fmt.Errorf("invalid token")
}

func main() {
    secretKey := []byte("your-256-bit-secret")
    userID := "12345"

    // 生成 JWT
    token, err := generateJWT(userID, secretKey)
    if err != nil {
        fmt.Println("Error generating JWT:", err)
        return
    }

    fmt.Println("Generated JWT:", token)

    // 验证 JWT
    claims, err := verifyJWT(token, secretKey)
    if err != nil {
        fmt.Println("Error verifying JWT:", err)
        return
    }

    fmt.Println("User ID from JWT:", claims.UserID)
}

Tags:

最近发表
标签列表