JSON Web Token
(JWT
) 是一种开放标准 (RFC 7519),用于在网络应用环境中以安全的方式传递信息。它常用于身份验证和信息交换,尤其是在跨域认证的场景中。本文将介绍与 JWT 相关的几个重要方面,并通过图解帮助理解其原理和使用。
一、认证流程
- 用户使用账号(手机/邮箱/用户名)密码请求服务器
- 服务器验证用户账号是否和数据库匹配
- 服务器通过验证后发送给客户端一个 JWT Token
- 客户端存储 Token,并在每次请求时携带该 Token(如何携带?)
- 服务端验证 Token 值,并根据 Token 合法性返回对应资源(如何验证?)
二、跨域认证的问题
在现代 Web 应用中,跨域认证是一个常见问题。随着单页应用(SPA)和微服务架构的普及,前端和后端服务可能部署在不同的域名或端口下。这种情况下,传统的会话认证方式(如 Cookie)可能面临以下挑战:
- 同源策略:浏览器的同源策略限制了跨域请求,导致无法直接访问不同域的资源。
- 状态管理:使用 Cookie 进行认证时,必须在每次请求中携带 Cookie,增加了状态管理的复杂性。
- 安全性:需要确保跨域请求的安全性,防止 CSRF(跨站请求伪造)等攻击。
JWT 作为一种无状态的认证方式,能够有效解决这些问题。它通过在客户端存储令牌,避免了传统会话管理的复杂性。
三、JWT 的原理
JWT 的基本原理是将用户的身份信息和其他相关数据编码为一个签名的字符串。这个字符串包含三个部分:头部(Header)、载荷(Payload)和签名(Signature)。
- 头部:通常由两部分组成,类型(即 JWT)和签名算法(如 HMAC SHA256)。
- 载荷:包含用户信息和其他数据,如用户 ID、角色、过期时间等。
- 签名:通过将编码后的头部和载荷与密钥结合,使用指定的算法生成的签名,用于验证信息的完整性和真实性。
通过这种机制,JWT 能够在不同的域之间安全地传递用户身份信息。
JWT 的结构示意图
JWT = Header.Payload.Signature
+------------------------------------+
| Header |
| { |
| "alg": "HS256", |
| "typ": "JWT" |
| } |
+------------------------------------+
| Payload |
| { |
| "userId": "123", |
| "name": "John Doe", |
| "iat": 1516239022 |
| } |
+------------------------------------+
| Signature |
| HMACSHA256( |
| base64UrlEncode(header) + "." +. |
| base64UrlEncode(payload), secret) |
+------------------------------------+
四、JWT 的数据结构
JWT 的数据结构由三个部分组成,使用点(.
)分隔:
xxxxx.yyyyy.zzzzz
- xxxxx:编码后的头部,通常为 JSON 对象,包含 token 的类型和算法信息。
- yyyyy:编码后的载荷,包含声明(Claims),即用户的身份信息和其他相关数据。
- zzzzz:签名,由头部、载荷和密钥生成,确保数据未被篡改。
示例
一个简单的 JWT 可能看起来像这样:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
五、JWT 的使用方式
1. 用户登录
用户通过提供用户名和密码进行登录,服务器验证后生成 JWT,并将其返回给客户端。
2. 客户端存储
客户端可以将 JWT 存储在 localStorage
或 sessionStorage
中,作为后续请求的身份凭证。
3. 发送请求
在后续的 API 请求中,客户端将 JWT 作为 Authorization 头的一部分发送给服务器:
Authorization: Bearer <token>
4. 服务器验证
服务器接收到请求后,解析 JWT,验证签名和有效性,从而确定用户的身份。
六、JWT 的几个特点
1. 无状态
JWT 是无状态的,服务器不需要存储会话信息,所有信息都包含在 JWT 中。这使得扩展和负载均衡变得简单。
2. 自包含
JWT 包含所有必要的信息,客户端可以独立地进行身份验证,无需额外的数据库查询。
3. 支持跨域
由于 JWT 是一个字符串,可以轻松地在不同的域之间传递,解决了跨域认证的问题。
4. 安全性
通过签名机制,JWT 确保了信息的完整性和真实性。可以使用对称或非对称加密算法增强安全性。
5. 可扩展性
JWT 可以包含自定义的声明(Claims),使得开发者可以根据需要扩展用户信息。