当前位置: 首页 > news >正文

一文读懂 JWT(JSON Web Token)

🔐 一文读懂 JWT(JSON Web Token)

一、什么是 JWT?

  • JWT(JSON Web Token)
    一种基于 JSON 的开放标准(RFC 7519),用于在各方之间安全地传递信息。
  • 特点
    1. 紧凑(Compact):可通过 URL、POST 参数或 HTTP 头传输
    2. 自包含(Self-contained):携带了用户的基本身份信息和声明(Claims)
    3. 可验证(Verifiable):签名保证数据未被篡改

📌 典型场景:用户登录后,服务器颁发一个 JWT,客户端每次请求都携带它,无需再查数据库做 Session 验证。


二、JWT 的三部分结构

一个典型的 JWT 长这样:

xxxxxxx.yyyyyyy.zzzzzzz
部分用途示例内容
Header(头部)指定算法和类型{"alg":"HS256","typ":"JWT"}
Payload(负载)存放声明(Claims),如用户 ID、过期时间等{"sub":"1234567890","name":"Alice","exp":1600000000}
Signature(签名)保证前两部分不被篡改HMACSHA256(Base64Url(Header) + "." + Base64Url(Payload), Secret)

注意:Header 和 Payload 都要做 Base64Url 编码!

JWT = Base64Url(Header) + "." + Base64Url(Payload) + "." + Base64Url(Signature)

三、JWT Secret(密钥)介绍 🔑

  1. 作用
    • 对称签名(HS256/HS384/HS512)中,Secret 用来签发验证 Token。
  2. 形式 & 长度
    • 高强度随机字节,建议 ≥256 bits(32 bytes)
    • 常见编码:
      • URL-Safe Base64
        9d6bXFMmZ3RV8Ytp9rz8QpKBuGV9zZ4T5vHSuJEjw8M
        
      • Hex
        e75ab5c53266774557c62da7dacfc429281b8695f736784f9bc74ae24923c3c30
        
  3. 如何生成?
    • Go 代码示例:
      import ("crypto/rand""encoding/base64""log"
      )func generateSecret() string {b := make([]byte, 32)if _, err := rand.Read(b); err != nil {log.Fatalf("生成 Secret 失败:%v", err)}// RawURLEncoding 去掉末尾 = 号,更 URL-Safereturn base64.RawURLEncoding.EncodeToString(b)
      }
      
  4. 泄露后果
    1. 攻击者可伪造任意合法 JWT,冒充用户或管理员
    2. 权限绕过、数据篡改、系统信任链崩溃
    3. 等同「根密钥」被盗,所有鉴权瞬间失效
  5. 防护 & 补救
    • 安全存储:✨使用 Vault、AWS KMS、GCP Secret Manager 等
    • 定期轮换(Key Rotation):支持「新」+「旧」秘钥平滑过渡
    • 缩短生命周期:结合 exp,让 Token & Secret 都有“有效期”
    • 多重验证:对支付、重置密码等关键操作再做一次二次校验
    • 监控告警:异常签名、同账户多地登录及时告警并强制登出

四、签名算法(alg)

算法名称描述
HS256HMAC + SHA-256,对称加密(Shared Secret)
HS384HMAC + SHA-384
HS512HMAC + SHA-512
RS256RSA + SHA-256,非对称加密(公钥/私钥对)
ES256ECDSA + SHA-256,椭圆曲线数字签名算法

小项目常用 HS256;高安全需求可选 RS256(私钥签发、公钥验签)。


五、JWT 的工作流程

  1. 用户登录(提供用户名/密码)
  2. 服务器验证成功后,签发 JWT
  3. 客户端保存(LocalStorage / Cookie)
  4. 后续请求携带 JWT
    • 推荐:请求头 Authorization: Bearer <token>
  5. 服务器 验证签名 & 检查声明(如是否过期、是否有权限)
  6. 验证通过,返回数据;否则 401 Unauthorized
UserClientServer输入用户名 & 密码POST /login返回 JWT(Header.Payload.Signature)GET /profile + Authorization: Bearer <JWT>返回 200 OK + 用户信息UserClientServer

六、签名 & 验证(HS256 示例)

1. 签名生成

H = Base64Url(Header)
P = Base64Url(Payload)
Secret = 服务器持有的密钥

LaTeX 公式版:

Signature=HMACSHA256(H+"."+P, Secret) \mathrm{Signature} = \mathrm{HMACSHA256}\bigl(H + "." + P,\ \mathrm{Secret}\bigr) Signature=HMACSHA256(H+"."+P, Secret)

2. 验证流程

  1. 拆分 Header.Payload.Signature
  2. 重新计算 HMACSHA256(H+"."+P, Secret)
  3. 对比结果:
    • 相同:✅ 数据未被篡改
    • 不同:❌ 拒绝访问

七、优缺点一览

优点缺点
1. 无状态(Stateless),可水平扩展 🌐1. 无法即时「撤销」已签发的 Token
2. 携带信息自包含,无需多次查询数据库 📦2. Token 泄露风险大,需妥善存储
3. 支持跨域认证(适合微服务、移动端)📱🌍3. Payload 明文可读,敏感信息请勿存放

八、实战示例(Go 语言版)

下面用 Go + 标准库 + github.com/golang-jwt/jwt/v4 库演示:

package mainimport ("crypto/rand""encoding/base64""fmt""log""net/http""strings""time""github.com/golang-jwt/jwt/v4"
)// 1. 生成 Secret
func generateSecret() string {b := make([]byte, 32)if _, err := rand.Read(b); err != nil {log.Fatalf("生成 Secret 失败:%v", err)}return base64.RawURLEncoding.EncodeToString(b)
}// 全局 Secret(示例中硬编码,生产环境请用安全存储)
var SECRET = generateSecret()// 2. 签发 JWT
func createToken(username string) (string, error) {claims := jwt.MapClaims{"sub": username,"name": "Alice","iat": time.Now().Unix(),"exp": time.Now().Add(time.Hour).Unix(),}token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)return token.SignedString([]byte(SECRET))
}// 3. 验证 JWT
func verifyToken(tokenStr string) (*jwt.Token, error) {return jwt.Parse(tokenStr, func(t *jwt.Token) (interface{}, error) {if _, ok := t.Method.(*jwt.SigningMethodHMAC); !ok {return nil, fmt.Errorf("unexpected signing method: %v", t.Header["alg"])}return []byte(SECRET), nil})
}func main() {http.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {// 仅示例:实际应解析 JSON & 验证数据库username, password := r.URL.Query().Get("user"), r.URL.Query().Get("pass")if username == "alice" && password == "123" {token, err := createToken(username)if err != nil {http.Error(w, "Token 签发失败", 500)return}fmt.Fprintf(w, `{"token":"%s"}`, token)return}http.Error(w, "用户名或密码错误", 401)})http.HandleFunc("/profile", func(w http.ResponseWriter, r *http.Request) {auth := r.Header.Get("Authorization")parts := strings.SplitN(auth, " ", 2)if len(parts) != 2 || parts[0] != "Bearer" {http.Error(w, "缺少或无效的 Authorization 头", 401)return}token, err := verifyToken(parts[1])if err != nil || !token.Valid {http.Error(w, "Token 无效或已过期", 401)return}claims := token.Claims.(jwt.MapClaims)fmt.Fprintf(w, `{"user":"%s","name":"%s"}`, claims["sub"], claims["name"])})log.Printf("🔑 Secret(演示用): %s\n", SECRET)log.Println("🚀 Server 启动: http://localhost:8080")log.Fatal(http.ListenAndServe(":8080", nil))
}

启动后:

  1. 登录:
    GET http://localhost:8080/login?user=alice&pass=123
  2. 拿到 {"token":"..."}
  3. 请求受保护路由:
    GET /profile HTTP/1.1
    Host: localhost:8080
    Authorization: Bearer <token>
    

九、总结 & 小贴士

  1. Secret 存储
    • 生产环境切勿硬编码,使用专业密钥管理服务(Vault, AWS KMS…)
  2. Token 生命周期
    • 设置合理 exp,并对关键操作做二次校验
  3. 安全细节
    • Payload 明文可读,切勿存敏感数据
    • 定期轮换 Secret,缩小泄露风险窗口
    • 始终启用 HTTPS,防止中间人攻击

🎉 至此,你已经掌握了 JWT 的核心原理、结构、Secret 要点、使用流程及 Go 实战示例。快去项目中试一试吧!

http://www.dtcms.com/a/300801.html

相关文章:

  • 使用橙武低代码平台做数据统计:定时任务汇总数据并生成日报表
  • 零基础学习性能测试:JVM性能分析与调优-JVM垃圾回收机制,GC对性能的影响
  • Gradio.NET 中文快速入门与用法说明
  • Python-初学openCV——图像预处理(四)——滤波器
  • Python 数据分析(四):Pandas 进阶
  • 负载均衡Haproxy
  • [NOIP 2004 提高组] 合并果子 Java
  • Vue 框架 学习笔记
  • 《汇编语言:基于X86处理器》第10章 结构和宏(1)
  • 【任务6.15】字符串操作
  • 51c自动驾驶~合集9
  • 以太坊ETF流入量超越比特币 XBIT分析买币市场动态与最新价格
  • 51核和ARM核单片机OTA实战解析(二)
  • docker与k8s的容器数据卷
  • 接口自动化-allure报告
  • 从零开始:Coze Studio开源版部署全记录(win11)
  • Leetcode力扣解题记录--第136题(查找单数)
  • note22:应用安全编码规范培训
  • 从零开始学习Dify-基于MCP的智能旅行规划助手上(八)
  • Windows10系统使用Cmake4.1.0构建工具+Visual Studio2022编译Opencv4.11教程
  • Jangow靶机通关教程
  • DAY21-二叉树的遍历方式
  • Gradio全解8——ChatInterfaceChatbot:聊天界面类与聊天机器人(3)——ChatInterface的多模态功能与附加输入输出
  • 9-大语言模型—Transformer 核心:多头注意力的 10 步拆解与可视化理解
  • 新手向:MySQL配置性能优化
  • unity开发中Hash、Queue、LinkedList简单介绍
  • 算法竞赛阶段二-数据结构(37)数据结构动态链表list
  • QT开发---网络编程下
  • 《C++》STL--string详解(上)
  • Linux文件理解,基础IO理解