JWT的组成

前言

本文谈谈 【JWT 的组成部分】 目标是看完之后,需要能用自己的语言说出【JWT 由哪几部分构成,各部分的作用是什么】

正文

JWT(JSON Web Token) 是一种开放标准(RFC 7519),它定义了一种紧凑的(Compact)自包含的(Self-contained) 方式,用于在各方之间安全地传输信息作为 JSON 对象。

这些信息可以被验证信任 ,因为它是数字签名 的。JWT 可以使用密钥(HMAC 算法) 或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。

一个 JWT 实际上就是一个字符串,它由三部分组成,用点(.)分隔开,格式如下:

css 复制代码
header.payload.signature

也就是:

复制代码
xxxxx.yyyyy.zzzzz

这三部分分别是:

  1. Header (头部)
  2. Payload (有效载荷)
  3. Signature (签名)

下面我们来详细拆解每一部分。


1. Header (头部)

作用 :描述 JWT 的元数据(Metadata) ,最主要的是声明签名算法令牌类型

  • 典型内容
    • alg (algorithm):签名使用的算法 。例如 HS256 (HMAC SHA-256) 或 RS256 (RSA SHA-256)。
    • typ (type):令牌类型 。通常就是 JWT
  • 数据处理流程
    1. 这个 JSON 对象会通过 Base64Url 编码(一种针对 URL 安全的 Base64 编码),形成 JWT 的第一部分

示例: 一个原始的 Header JSON:

json 复制代码
{
    "alg": "HS256",
    "typ": "JWT"
}

经过 Base64Url 编码后,得到 JWT 的第一部分:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

🔍 小提示!!!:Base64 是一种编码方式,不是加密!!!所以 Header 部分的内容任何人都可以解码看到。你可以直接把上面的编码字符串拿去任何在线 Base64 解码工具解码,就能还原出原始的 JSON。


2. Payload (有效载荷)

作用 :携带实际的声明(Claims)。声明就是关于实体(通常是用户)和其他数据的语句。

  • 声明类型
    • 注册声明(Registered Claims) :预定义的一组标准声明,非强制但推荐使用,用于提供一组有用的、可互操作的声明。
      • iss (issuer):签发者
      • sub (subject):主题(通常是用户 ID)。
      • aud (audience):接收方
      • exp (expiration time):过期时间(Unix 时间戳)。
      • nbf (not before):生效时间,在此时间之前令牌无效。
      • iat (issued at):签发时间
    • 公共声明(Public Claims) :可以随意定义的声明,但为了避免冲突,应该在 IANA JSON Web Token Registry 中定义它们,或者使用一个防冲突的命名空间(如包含域名)。
    • 私有声明(Private Claims) :在提供者和消费者之间共同约定 的、用于共享信息的自定义声明,既不是注册声明也不是公共声明。
      • 例如:username, role 等。
  • 数据处理流程
    1. Payload 的 JSON 对象同样会通过 Base64Url 编码,形成 JWT 的第二部分

示例: 一个原始的 Payload JSON:

json 复制代码
{
    "sub": "1234567890",
    "name": "John Doe",
    "iat": 1516239022,
    "admin": true
}

经过 Base64Url 编码后,得到 JWT 的第二部分:eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJhZG1pbiI6dHJ1ZX0

⚠️ 重要提醒 :和 Header 一样,Payload 也仅仅是 Base64Url 编码 ,【并非加密】!!!。绝对不要在 JWT 的 Payload 或 Header 中放置敏感信息(如密码),除非整个 JWT 被额外加密了(参见 JWE)。


3. Signature (签名)

作用 :这是 JWT 的安全核心 。用于验证消息在传输过程中没有被篡改,并且对于使用私钥签名的令牌,它还可以验证发送方的身份。

  • 生成方式
    1. 编码后的 Header编码后的 Payload ,用一个点(.)连接起来,形成一个字符串:base64UrlEncode(header) + "." + base64UrlEncode(payload)
    2. 使用在 Header 中指定的签名算法(如 HS256),和一个密钥(Secret)私钥(Private Key) ,对这个连接起来的字符串进行签名

以 HS256 为例的签名公式

scss 复制代码
signature = HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

然后将签名结果(一个二进制哈希值)也进行 Base64Url 编码,形成 JWT 的第三部分

示例 : 假设我们的密钥是字符串 "your-256-bit-secret"。 对 eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJhZG1pbiI6dHJ1ZX0 进行 HMAC-SHA256 签名并编码后,得到第三部分:SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

🛡️ 核心价值 :签名是关键!即使 Header 和 Payload 可以被任何人解码查看,但无法被篡改。因为服务器在收到 JWT 后,会用同样的密钥和算法重新计算前两部分的签名,如果计算结果与第三部分不匹配,就说明令牌被篡改了,应立即拒绝。


最终的 JWT

将上面三个用点分隔的 Base64Url 字符串拼接起来,就形成了一个完整的 JWT:

复制代码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJhZG1pbiI6dHJ1ZX0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

我们可以用一个简单的流程图来回顾 JWT 的生成过程:

text 复制代码
【生成 JWT】
┌─────────────────┐    ┌──────────────────┐    ┌──────────────────┐
│  1. Header      │    │  2. Payload      │    │  3. Signature    │
│                 │    │                  │    │                  │
│ {               │    │ {                │    │ 取前两部分编码结果:│
│   "alg": "HS256",│    │   "sub": "123...", │    │ header_b64 + "."  │
│   "typ": "JWT"  │    │   "name": "Jo...",  │    │   + payload_b64   │
│ }               │    │   ...            │    │                  │
│                 │    │ }                │    │ 用密钥(Secret)   │
└─────────────────┘    └──────────────────┘    │ 和Header中指定   │
         |                      |               │ 的算法(alg)进行  │
         ↓ (Base64Url 编码)     ↓ (Base64Url 编码)│ 签名(HMAC等)     │
┌─────────────────┐    ┌──────────────────┐    │                  │
│   header_b64    │    │   payload_b64    │    │ 得到签名后同样   │
│ "eyJhbGc..."    │    │ "eyJzdWI..."     │    │ 进行Base64Url编码│
└─────────────────┘    └──────────────────┘    │                  │
         \_________________________/           └──────────────────┘
                      |                                    |
                      ↓ (用点 . 连接)                       ↓ (编码后)
                header_b64 + "." + payload_b64        signature_b64
                      \_________________________ ________________/
                                               |
                                               ↓ (最终用点 . 连接)
                    最终JWT = header_b64 + "." + payload_b64 + "." + signature_b64

验证 JWT 时,服务端会做反向操作

  1. 将 JWT 按点分割成三部分。
  2. 用相同的密钥和算法,对前两部分重新计算签名。
  3. 将自己计算的签名与 JWT 自带的第三部分签名进行安全的比对(防止计时攻击)。
  4. 如果签名一致,则证明令牌有效且未被篡改;同时,可以解码 Payload 提取其中的信息(如用户 ID、权限等)。

最后

我们来回答开头的问题:JWT 由哪几部分构成,各部分的作用是什么?

JWT 由三部分组成,用点(.)分隔:

  1. Header(头部):经过 Base64Url 编码的 JSON 对象,主要声明签名算法(alg)和令牌类型(typ)。
  2. Payload(有效载荷):经过 Base64Url 编码的 JSON 对象,携带了实际的声明(Claims),如用户身份(sub)、过期时间(exp)等自定义信息。
  3. Signature(签名):对前两部分连接后的字符串,通过指定的算法和密钥进行签名并编码的结果,是验证令牌完整性和真实性的核心。

核心要点 :Header 和 Payload 仅是编码,不加密,切勿存放敏感信息。JWT 的安全性完全依赖于签名。

相关链接

相关推荐
北风朝向3 小时前
Spring Boot参数校验8大坑与生产级避坑指南
java·spring boot·后端·spring
canonical_entropy3 小时前
一份关于“可逆计算”的认知解码:从技术细节到哲学思辨的完整指南
后端·低代码·deepseek
趙卋傑4 小时前
项目发布部署
linux·服务器·后端·web
数据知道5 小时前
Go基础:Go语言能用到的常用时间处理
开发语言·后端·golang·go语言
不爱编程的小九九5 小时前
小九源码-springboot048-基于spring boot心理健康服务系统
java·spring boot·后端
龙茶清欢5 小时前
Spring Boot 应用启动组件加载顺序与优先级详解
java·spring boot·后端·微服务
235166 小时前
【LeetCode】3. 无重复字符的最长子串
java·后端·算法·leetcode·职场和发展
可观测性用观测云7 小时前
解锁DQL高级玩法——对日志关键信息提取和分析
后端
Chan167 小时前
【 设计模式 | 结构型模式 代理模式 】
java·spring boot·后端·设计模式·intellij-idea