Go语言使用golang-jwt/jwt/v4进行JWT鉴权详解

雨后青山
雨后青山
发布时间:2026-10-15| 2人浏览过
原创

针对jwt-go仓库停止维护的现状,推荐使用github.com/golang-jwt/jwt/v4。本文基于Go语言,详解JWT的Header、Payload、Signature组成原理,并提供从安装、生成到解析验证的完整v4版本代码实践。

为什么选择v4版本

原生的jwt-go仓库已不再维护,官方建议迁移至github.com/golang-jwt/jwt/v4。目前网络上多数教程仍停留在v3版本,而在Go项目中引入v4能确保获得更稳定的安全支持和兼容性。

JWT数据结构原理

JSON Web Token (JWT)是一个开放标准(RFC 7519),用于在各服务间安全传输信息,特别适用于分布式站点SSO场景。实际的JWT由三部分组成,中间用点(.)分隔,格式为Header.Payload.Signature。

Header(头部)

Header通常包含两部分:声明类型(typ)和使用的签名算法(alg)。默认算法是HMAC SHA256(HS256)。

{
  "alg": "HS256",
  "typ": "JWT"
}

该JSON对象经Base64URL编码后构成第一部分。

Payload(负载)

Payload存放有效载荷数据,包含7个官方注册字段:

  • iss(签发人)、exp(过期时间)、sub(主题)、aud(受众)、nbf(生效时间)、iat(签发时间)、jti(编号)。

开发者也可自定义字段,但需注意JWT默认不加密,请勿存入敏感秘密信息。

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

Signature(签名)

为了防止篡改,需要指定一个只有服务器知道的密钥(Secret)。通过Header中指定的算法对Base64URL编码后的Header和Payload进行签名计算:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

Base64URL规则

与标准Base64不同,Base64URL移除了URL特殊字符:=省略、+替换为-、/替换为_。这种设计确保了Token可以直接放入URL参数或HTTP Header中传递。

Go语言集成与实操

第1步:安装依赖

由于v4版本引入了Breaking Changes,需通过go get明确获取新版本:

go install "github.com/golang-jwt/jwt/v4"

第2步:定义Claims结构体

v4版本中,官方将原来的StandardClaims重命名为RegisteredClaims并内置到核心包中。继承此类便于扩展业务数据(如手机号)。

import (
    "github.com/golang-jwt/jwt/v4"
    "time"
)

type MyClaims struct {
    Phone string `json:"phone"`
    jwt.RegisteredClaims
}

// 注意:生产环境中应使用环境变量管理secret,避免硬编码
var MySecret = []byte("your-secret-key")

第3步:生成Token

实例化jwt.NewWithClaims指定算法(此处使用HS256),设置签发时间、生效时间和过期时间,最后调用SignedString输出Token字符串。

func MakeToken(phone string) (string, error) {
    // 设置Token有效期为3小时
    claim := MyClaims{
        Phone: phone,
        RegisteredClaims: jwt.RegisteredClaims{
            ExpiresAt: jwt.NewNumericDate(time.Now().Add(3 * time.Hour)),
            IssuedAt:  jwt.NewNumericDate(time.Now()),
            NotBefore: jwt.NewNumericDate(time.Now()),
        },
    }
    token := jwt.NewWithClaims(jwt.SigningMethodHS256, claim)
    return token.SignedString(MySecret)
}

第4步:解析并验证Token

使用jwt.ParseWithClaims时,必须传入对应的Claims结构体指针和用于验签的KeyFunc。

风险提示:KeyFunc若处理不当可能引发“Invalid Key”错误。以下写法仅用于快速调试,建议在正式环境增加对签名算法的安全校验逻辑。

func ParseToken(tokenStr string) (*MyClaims, error) {
    token, err := jwt.ParseWithClaims(tokenStr, &MyClaims{}, func(t *jwt.Token) (interface{}, error) {
        return MySecret, nil
    })

    if err != nil {
        if ve, ok := err.(*jwt.ValidationError); ok {
            if ve.Errors == jwt.ValidationErrorMalformed {
                return nil, fmt.Errorf("not even a token")
            } else if ve.Errors == jwt.ValidationErrorExpired {
                return nil, fmt.Errorf("token is expired")
            } else if ve.Errors == jwt.ValidationErrorNotValidYet {
                return nil, fmt.Errorf("token not active yet")
            }
        }
        return nil, err
    }

    if claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
        return claims, nil
    }
    return nil, errors.New("couldn't handle this token")
}

常见问题排查

  • 报错 invalid key: 请检查Parse时的Secret是否与生成时完全一致(区分大小写)。
  • 版本混淆: 确认项目中引用的都是 v4。如果混用了旧版标准库,可能会导致 RegisteredClaims 找不到或签名算法报错。

总结

以上就是Go语言中使用golang-jwt/jwt/v4进行JWT身份验证的详细内容,更多关于Golang API安全及Token管理的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。