JWT 初学者指南 — 简单数学类比
Source: Dev.to
Introduction
当用户登录时,服务器需要在每一次请求中记住他们的身份。传统的会话把数据存储在服务器上,而 JWT(JSON Web Token)则把用户信息——例如用户 ID、角色和过期时间——直接打包进令牌中。服务器随后只需在每次请求时验证签名,避免了数据库查询。
JWT Structure
JWT 由三部分组成,用点号连接:
header.payload.signature
Header
Header 指定签名算法(例如 HS256 或 RS256)以及令牌类型。
Payload
Payload 包含实际的用户数据,称为 claims。常见的 claims 包括:
sub→ 主体(用户 ID)iss→ 发行者aud→ 受众exp→ 过期时间iat→ 签发时间
Signature
Signature 确保令牌的完整性。生成过程如下,服务器:
- 对 Header 和 Payload 进行 Base64 编码。
- 用点号(
.)将它们连接,形成 message。 - 使用哈希函数并结合密钥(或私钥)生成签名。
随后将签名附加到令牌后面。
Token Verification
1. HS256(对称)
生成令牌和验证令牌使用相同的密钥。
类比:
- 密钥 = 3
- 签名规则 = 用密钥相乘
令牌生成
message = 10
signature = message * secret # 10 * 3 = 30
token = 10.30
令牌校验
received_token = 10.30
recalculated_signature = 10 * 3 # 30
recalculated_signature == 30 # → 有效
如果攻击者修改了消息:
received_token = 18.30
recalculated_signature = 18 * 3 # 36
recalculated_signature == 30 # → 无效
2. RS256(非对称)
服务器使用 私钥 进行签名;验证使用 公钥。这使得多个服务可以在不共享私钥的情况下验证令牌。
简化类比(非真实 RSA):
私钥操作 = 乘以 3
公钥操作 = 除以 3
签名(令牌生成)
message = 10
signature = message * 3 # 30
token = 10.30
验证
received_token = 10.30
expected_message = signature / 3 # 30 / 3 = 10
expected_message == 10 # → 有效
修改后的消息
received_token = 20.30
expected_message = 30 / 3 # 10
expected_message == 20 # → 无效
错误的公钥
public_key = divide by 5
expected_message = 30 / 5 # 6
expected_message == 10 # → 无效
Important Security Note
Payload 仅仅是 Base64 编码,而不是加密。任何人都可以解码并读取其内容。因此,切勿在 JWT 中存放敏感数据(例如密码)。签名保证令牌未被篡改,但它 不 隐藏数据。