【Web】JWT(JSON Web Token)技术详解
文章目录
-
-
- 1. JWT 是什么?一个生动的比喻
- 2. JWT 的结构
-
- 第一部分:Header (头部)
- 第二部分:Payload (载荷)
- 第三部分:Signature (签名)
- 3. JWT 的工作流程(结合你的场景)
-
- 步骤 1:用户登录,Core API 颁发 JWT
- 步骤 2:前端携带 JWT 访问 Core API
- 步骤 3:Core API 请求 Helper Service(服务间鉴权)
- 4. JWT 的核心优势
- 5. JWT 的致命缺陷与安全考量
-
- 缺陷 1:无法主动失效
- 缺陷 2:Payload 信息泄露
- 缺陷 3:密钥管理至关重要
- 6. JWT vs. 传统 Session
- 7. 在你的场景中如何具体实现
-
- Core API (签发者)
- Helper Service (验证者)
-
1. JWT 是什么?一个生动的比喻
想象一下,你去一个大型游乐园(你的网站)。
- 传统 Session 方式:
你在门口买票,售票处(后端)给你一张手环(Session ID),上面只有一个随机号码。你每玩一个项目(请求一个 API),工作人员(后端)都要扫描你的手环,然后通过对讲机问售票处:这个号码是谁?有效吗?还有余额吗?” 售票处查一遍记录,再告诉工作人员。如果游乐园很大,游客很多,售票处(后端服务器)会非常忙。 - JWT 方式:
你在门口买票,售票处(后端)给你一张加密的、信息丰富的智能门票(JWT)。这张门票上用防伪技术写着你的名字、有效期、可以玩哪些项目(权限)等信息。你每玩一个项目,工作人员(后端)只需用**专用的验票机(密钥)**扫一下门票的防伪码(签名),就能立即确认:- 这张门票确实是我们游乐园发的(验证签名)。
- 门票没过期(验证
exp
)。 - 门票上写的你可以玩这个项目(验证权限
scope
)。
工作人员完全不需要再打电话问售票处,因为所有必要的信息都在这张自包含的门票上。
核心定义:JWT(JSON Web Token)是一种开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于在各方之间以 JSON 对象安全地传输信息。这个信息可以被验证和信任,因为它是经过数字签名的。
2. JWT 的结构
一个 JWT 实际上是一个很长的字符串,由三部分组成,用点(.
)分隔:
Header.Payload.Signature
我们来看一个真实的例子:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE3MDAwMDAwMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
第一部分:Header (头部)
它是一个 JSON 对象,描述了 JWT 的元数据,通常包含两个部分:
alg
(Algorithm):签名算法,例如HS256
(HMAC-SHA256)、RS256
(RSA-SHA256)。typ
(Type):令牌类型,通常就是JWT
。
{"alg": "HS256","typ": "JWT"
}
然后,这个 JSON 对象会被 Base64Url 编码,形成 JWT 的第一部分。
小知识:Base64Url 编码和普通的 Base64 编码类似,但会将
+
替换为-
,/
替换为_
,并去掉末尾的=
,使其可以在 URL 中安全传输。
第二部分:Payload (载荷)
它也是一个 JSON 对象,包含了实际要传递的数据,即声明。声明分为三类:
- 标准声明(Registered Claims):这是 JWT 规范里预定义的,虽然不是强制性的,但推荐使用,它们提供了有用的信息。
iss
(Issuer):签发者。sub
(Subject):主题,通常是用户 ID。aud
(Audience):接收方,指明这个 JWT 是给谁用的。exp
(Expiration Time):过期时间,是一个 Unix 时间戳。这是最重要的声明之一!nbf
(Not Before):生效时间,在此之前 JWT 不可用。iat
(Issued At):签发时间。jti
(JWT ID):JWT 的唯一标识,用于防止重放攻击。
- 公共声明(Public Claims):可以由使用 JWT 的各方随意定义。但为了避免冲突,应该把它们定义在 IANA JSON Web Token Registry 中,或者使用一个唯一的命名空间,如 URI。
- 私有声明(Private Claims):这是在同意使用它们的各方之间共享信息的自定义声明。例如,可以添加
userId
,username
,roles
等。
{"sub": "1234567890", // 用户ID"name": "John Doe", // 用户名"iat": 1516239022, // 签发时间"exp": 1700000000, // 过期时间"roles": ["editor", "guest"] // 自定义的私有声明:用户角色
}
同样,这个 JSON 对象也会被 Base64Url 编码,形成 JWT 的第二部分。
⚠️ 极其重要的安全警告:Payload 只是 Base64 编码,不是加密! 任何人都可以解码并看到里面的内容。因此,永远不要在 Payload 中存放敏感信息,如密码、信用卡号、个人隐私等。
第三部分:Signature (签名)
签名是 JWT 的安全灵魂。它用于验证消息在传输过程中没有被篡改,并且对于使用私钥签名的令牌,它还可以验证发送者的身份。
签名的生成过程如下:
- 将 编码后的 Header 和 编码后的 Payload 用点(
.
)连接起来。 - 将连接后的字符串,使用 Header 中指定的签名算法(
alg
)和一个密钥进行签名。 - 将生成的签名部分进行 Base64Url 编码,形成 JWT 的第三部分。
以HS256
(HMAC-SHA256) 算法为例:
HMACSHA256(base64UrlEncod