JWT(JSON Web Token)是一种基于 JSON 的开放标准(RFC 7519),用于在各方之间作为 JSON 对象传输信息。由于其具有数字签名,可以确保信息是经过验证的和可信的。JWT 的常见应用场景包括前端与后端之间的认证和授权。
JWT 的结构
JWT 由三部分组成,每部分之间用点(.
)分隔:
- Header(头部):通常包括两部分:令牌的类型(即 JWT)和使用的签名算法(如 HMAC SHA256 或 RSA)。
- Payload(载荷):这是实际的声明信息。它包含一些有意义的信息(claims),可以分为三类:
- Registered claims:预定义的声明集(如
iss
,exp
,sub
,aud
)。 - Public claims:可以自由定义的声明,使用时应避免与其他公共声明冲突。
- Private claims:双方之间商定使用的声明。
- Registered claims:预定义的声明集(如
- Signature(签名):用于验证消息的真实性和完整性。签名是通过将 header 和 payload 的 base64url 编码串联起来,用密钥和指定的算法进行签名。
JWT 的工作流程
- 用户登录:用户在前端应用中输入登录信息。
- 服务器验证:前端将用户登录信息发送到后端服务器,后端验证用户信息。
- 生成 JWT:如果验证通过,服务器会生成一个 JWT,并将其返回给前端。这个 JWT 包含了用户的身份信息和过期时间等。
- 前端存储 JWT:前端通常会将 JWT 存储在浏览器的 localStorage 或 sessionStorage 中。
- 请求带 JWT:在后续的请求中,前端会将 JWT 附加到请求头(通常是
Authorization
字段)中发送给服务器。 - 服务器验证 JWT:服务器接收到请求后,会验证 JWT 的签名和有效期。如果 JWT 有效,服务器会处理请求并返回相应的响应。
JWT 在前端与后端交互中的优势
- 无状态:服务器无需存储用户会话信息,所有需要的信息都包含在 JWT 中,使得服务器变得无状态。
- 跨域支持:因为 JWT 是基于标准的 HTTP 头传递,可以方便地用于跨域认证。
- 灵活性:可以在 JWT 的 payload 中存储任意用户信息,且可以使用不同的签名算法。
一个简单的例子
假设有一个前端应用和后端 API,用户登录的过程如下:
-
用户登录:
fetch('https://example.com/api/login', { method: 'POST', body: JSON.stringify({ username: 'user', password: 'pass' }), headers: { 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => { localStorage.setItem('token', data.token); });
-
发送带 JWT 的请求:
const token = localStorage.getItem('token'); fetch('https://example.com/api/protected', { method: 'GET', headers: { 'Authorization': `Bearer ${token}` } }) .then(response => response.json()) .then(data => { console.log(data); });
在这个例子中,用户登录后,服务器会生成一个 JWT 并返回给前端,前端将其存储在 localStorage 中。以后所有需要认证的请求都会携带这个 JWT,服务器可以通过验证 JWT 来确认用户的身份并处理请求。
通过这种方式,JWT 实现了前端与后端之间的安全认证和授权。