Go (Golang) 中的 JWT 令牌:golang-jwt 库完全指南
JSON Web Token (JWT) 是一种基于 JSON 的开放标准 (RFC 7519),用于创建访问令牌。JWT 广泛应用于身份验证和各方之间的信息交换。在 Go (Golang) 中,最流行且积极维护的 JWT 库是 golang-jwt/jwt/v5。在本文中,我们将详细介绍如何安装、配置和使用该库来构建安全的 Web 应用程序。
安装 golang-jwt 库
首先,使用 go get 将库添加到您的项目中:
go get github.com/golang-jwt/jwt/v5安装后,在代码中导入该包:
import ( "github.com/golang-jwt/jwt/v5")JWT 的主要组成部分
JWT 由三个用点分隔的部分组成:Header(头部)、Payload(载荷)和 Signature(签名)。golang-jwt 库为处理每个部分提供了便捷的结构:
- Header — 包含关于令牌类型和签名算法的元数据(例如 HS256、RS256)。
- Payload — 包含声明(claims),例如用户 ID、过期时间、角色和其他数据。
- Signature — 使用密钥或密钥对(私钥/公钥)创建。
创建 JWT 访问令牌 (Access Token)
让我们看一个使用 HS256 算法(对称加密)创建访问令牌的示例。首先,定义一个包含自定义声明的结构体:
type CustomClaims struct { UserID int `json:"user_id"` Username string `json:"username"` jwt.RegisteredClaims}现在,创建一个生成令牌的函数:
func GenerateAccessToken(userID int, username string, secretKey []byte) (string, error) { claims := CustomClaims{ UserID: userID, Username: username, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)), IssuedAt: jwt.NewNumericDate(time.Now()), Subject: "access", }, }
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString(secretKey)}这里我们将令牌的生存时间设置为 15 分钟,这是访问令牌的标准做法。使用 jwt.NewNumericDate() 可以正确格式化时间。
验证和解析令牌
要验证令牌的真实性,需要提取声明并检查签名:
func ValidateToken(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("意外的签名方法: %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("无效的令牌")}在回调函数中检查签名算法非常重要,以避免算法替换攻击。
创建和刷新刷新令牌 (Refresh Token)
为了提高安全性,通常使用一对令牌:短生命周期的访问令牌和长生命周期的刷新令牌。刷新令牌允许在不重新输入用户名/密码的情况下获取新的访问令牌。
func GenerateRefreshToken(userID int, secretKey []byte) (string, error) {