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 的安全性完全依赖于签名。

相关链接

相关推荐
爱勇宝1 天前
第 1 章:别把“需求文档”当成真正的需求
前端·后端·程序员
IT_陈寒1 天前
闭包陷阱让我加了两天班,JavaScript你真行
前端·人工智能·后端
易协同低代码1 天前
通达OA核心类库TD类深度解析
后端
Gopher_HBo1 天前
Go语言学习笔记(十八)Gin处理Session
后端
谭光志1 天前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
她说..1 天前
Java 默认值设置方式
java·开发语言·后端·springboot
foggyprojects1 天前
从0开始,一句话启动AI DataAgent
后端·数据分析·ai编程
郡杰1 天前
一些基础和问题解决
后端
陈随易1 天前
前端项目部署只要30秒
前端·后端·程序员
YIAN1 天前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp