当前位置: 首页 > 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.xdnf.cn/news/1198945.html

相关文章:

  • 【LeetCode刷题指南】--设计循环队列
  • 怎样让阿里云服务器(centos)有界面
  • 机械学习----knn实战案例----手写数字图像识别
  • Kotlin位运算
  • 板凳-------Mysql cookbook学习 (十二--------3_3)
  • BUG记录——Request接传Json数据中文乱码
  • Spring Boot + @RefreshScope:动态刷新配置的终极指南
  • Keepalived + LVS-DR 高可用与负载均衡实验
  • Java全栈面试实战:从JVM到AI的技术演进之路
  • OpenResty 高并发揭秘:架构优势与 Linux 优化实践
  • Unity TAA
  • CentOS网卡未被托管解决记录
  • PDF文件被加密限制怎么办?专业级解除方案分享
  • Python|OpenCV-实现快速处理图像的方法(23)
  • GPT-4o实战应用指南:从入门到精通的技术心得
  • 昇思学习营-模型推理和性能优化
  • 【AcWing 838题解】堆排序
  • MySQL - 主从复制与读写分离
  • 一分钟部署一个导航网站
  • 递归查询美国加速-技术演进与行业应用深度解析
  • CentOS 9 配置国内 YUM 源
  • 2025第15届上海生物发酵展将于8月7号启幕
  • 高级 Tkinter:使用类
  • 通过不同坐标系下的两个向量,求解旋转矩阵
  • 《C++ list 完全指南:list的模拟实现》
  • 《频率之光:维度回响》
  • mac电脑安装docker图文教程
  • 【笔记】活度系数推导
  • Linux驱动21 --- FFMPEG 音频 API
  • 深度解析 inaSpeechSegmenter:高效音频语音分割与检测开源工具