JSON Web Token (JWT):跨域身份验证的热门方案
本文介绍了当下最流行的跨域身份验证解决方案——JSON Web Token (JWT) 的原理和使用方法。
一、跨域身份验证的挑战
互联网服务离不开用户身份验证。传统流程如下:
此模型的扩展性差:单机环境没问题,但服务器集群或跨域面向服务的架构则需要会话数据共享,每台服务器都能读取会话。例如,网站 A 和网站 B 是同一家公司的关联服务,要求用户登录其中一个网站后,访问另一个网站也能自动登录。一种解决方案是持久化会话数据,将其写入数据库或其他持久层,各服务收到请求后从持久层请求数据。此方案架构清晰,但工作量较大,且持久层故障会导致单点故障。另一种方案是服务器根本不保存会话数据,所有数据保存在客户端,每次请求都发送回服务器。JWT 正是这种方案的代表。
二、JWT 的原理
JWT 的原理是服务器验证后生成一个 JSON 对象并返回给用户,例如:
<code class="language-json">{"name": "Alice", "role": "admin", "expiration time": "2024年7月1日0:00"}</code>
之后用户与服务器通信时需要回传此 JSON 对象,服务器完全根据此对象确定用户身份。为防止用户篡改数据,服务器生成此对象时会添加签名(细节后述)。服务器不再保存任何会话数据,即服务器变为无状态的,更容易实现扩展。
三、JWT 的数据结构
实际的 JWT 类似这样:
它是一个很长的字符串,由点 (.) 分隔成三个部分。注意 JWT 内部没有换行符,此处分行只是为了便于显示。JWT 的三个部分如下:
一行表示为:Header.Payload.Signature
下面分别介绍这三个部分。
Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常如下:
<code class="language-json">{"alg": "HS256", "typ": "JWT"}</code>
其中 alg 属性表示签名算法,默认为 HMAC SHA256 (HS256);typ 属性表示此令牌的类型,JWT 令牌统一写为 JWT。此 JSON 对象最终使用 Base64URL 算法转换为字符串(细节后述)。
Payload 部分也是一个 JSON 对象,用于存储实际需要传输的数据。JWT 定义了 7 个官方字段可选:
除了官方字段,还可以自定义私有字段。例如:
<code class="language-json">{"name": "Alice", "role": "admin", "expiration time": "2024年7月1日0:00"}</code>
注意,JWT 默认不加密,任何人都可以读取,因此不要在此部分放置秘密信息。此 JSON 对象也需要使用 Base64URL 算法转换为字符串。
Signature 部分是前两部分的签名,用于防止数据篡改。首先需要指定一个密钥 (secret),此密钥只有服务器知道,不能泄露给用户。然后使用 Header 中指定的签名算法(默认为 HMAC SHA256)根据以下公式生成签名:
<code class="language-json">{"alg": "HS256", "typ": "JWT"}</code>
计算出签名后,将 Header、Payload 和 Signature 三部分组合成一个字符串,各部分之间用 "点" (.) 分隔,即可返回给用户。
如前所述,Header 和 Payload 的序列化算法是 Base64URL。此算法基本与 Base64 算法类似,但有一些细微差别。作为令牌,JWT 有时可能放在 URL 中(例如 api.example.com/?token=xxx),Base64 中的三个字符 、/ 和 = 在 URL 中有特殊含义,需要替换:= 被省略, 被替换为 -,/ 被替换为 _。这就是 Base64URL 算法。
四、JWT 的使用方法
客户端收到服务器返回的 JWT 后,可以将其存储在 Cookie 或 localStorage 中。之后客户端每次与服务器通信都需要携带此 JWT。可以将其放在 Cookie 中自动发送,但这无法跨域。更好的方法是将其放在 HTTP 请求头的 Authorization 字段中:
Authorization: Bearer
另一种方法是在跨域时将 JWT 放在 POST 请求的数据体中。
五、JWT 的几个特性
(1) JWT 默认不加密,但可以加密。生成原始 Token 后,可以用密钥再次加密。
(2) JWT 未加密的情况下,不能写入秘密数据。
(3) JWT 不仅可以用于身份验证,还可以用于信息交换。有效使用 JWT 可以减少服务器查询数据库的次数。
(4) JWT 最大的缺点是服务器不保存会话状态,无法在使用过程中撤销某个令牌或更改令牌的权限。也就是说,JWT 一旦发出,就一直有效直到过期,除非服务器部署额外逻辑。
(5) JWT 本身包含身份验证信息,一旦泄露,任何人都可以获得令牌的所有权限。为减少被盗,JWT 的有效期应设置得相对较短。对于一些更重要的权限,用户使用时应再次进行身份验证。
(6) 为减少被盗,JWT 不应使用 HTTP 协议明文传输,而应使用 HTTPS 协议传输。
Leapcell:最佳无服务器 Web 托管平台
最后,推荐一个部署 Web 服务的最佳平台:Leapcell
在文档中了解更多信息!
Leapcell Twitter:https://www.php.cn/link/7884effb9452a6d7a7a79499ef854afd
以上是掌握 JWT(JSON Web 令牌):深入探讨的详细内容。更多信息请关注PHP中文网其他相关文章!