回归面试题!
回答重点
JWT(JSON Web Token)是一种用于在各方之间传递安全信息的紧凑、URL安全的令牌格式。
在用户登录后,服务器生成JWT并返回给客户端。客户端在后续请求中通过HTTP头部(通常是Authorization
头)发送该JWT,服务器则验证该JWT的有效性以进行用户身份验证。
因为它的无状态性,常用于分布式系统和微服务架构中。
其结构主要包括三个部分:Header、Payload和Signature。
JWT的工作原理可以总结为以下几个步骤:
1)Header:描述令牌的元数据,通常包含令牌的类型(即JWT)和所使用的签名算法(如HMAC SHA256)。
2)Payload:包含声明(Claims),即传递的数据。这些数据通常包括用户信息和其他相关数据。常见的声明类型有iss
(发行者)、exp
(到期时间)、sub
(主题)等。
3)Signature:将Header和Payload用指定的算法进行签名,用以验证JWT的真实性和完整性。签名确保了令牌内容在传输过程中未被篡改。
JWT的优点:
- 自包含:JWT中包含了所有必要的信息,因此在验证时不需要查询数据库,提升了性能。
- 跨语言:由于JWT是基于JSON的,几乎所有编程语言都支持它的生成和解析。
扩展知识
如何废除一个未过期的 JWT
因为 JWT 是无状态的,一般服务器并不保存已签发的 JWT,所以服务器无法主动撤销一个已经签发的 JWT。不过可以通过其他方式来实现这个功能。
使用黑名单(Blacklist)
- 实现思路:在服务器端维护一个黑名单(或者叫作废列表),该列表包含所有已被废除的 JWT 标识符(通常使用 JWT 的
jti
声明)。每次服务器验证 JWT 时,除了验证签名和其他标准信息外,还需要检查该 JWT 是否在黑名单中。 - 优点:可以精确废除特定的 JWT,不影响其他合法的 JWT。
- 缺点:需要在服务器端存储和管理黑名单,违背了 JWT 的无状态特性,增加了系统复杂度。如果黑名单列表变大,查询效率可能成为问题。
使用版本控制(Token Versioning)
- 实现思路:在用户信息中引入一个“Token 版本号”的字段,每次生成 JWT 时,将这个版本号作为 JWT 的一部分(可以放在 Payload 的自定义声明中)。当需要废除某个用户的 JWT 时,只需将用户的版本号递增。在服务器验证 JWT 时,检查 JWT 中的版本号与用户当前的版本号是否匹配,若不匹配,则视为无效。
- 优点:无需维护黑名单,可以较容易地废除特定用户的所有 JWT。
- 缺点:在多用户、多设备情况下,如果一个设备上的 JWT 被废除,所有设备上的 JWT 都会失效。需要在服务器端存储和管理用户的版本号。
结合状态信息
- 实现思路:在某些场景下,可以在服务器端结合一些状态信息来决定 JWT 是否有效。例如,在用户注销或更改密码时,更新服务器上的某些状态。当用户发出请求时,除了验证 JWT 外,服务器还检查这些状态是否符合要求,不符合时即使 JWT 有效,也拒绝请求。
- 优点:灵活性高,可以根据具体业务需求决定 JWT 的有效性。
- 缺点:需要服务器端保存一定的状态信息,违背了无状态设计的初衷,且具体实现较为复杂。
JWT的安全性考虑
- 签名与加密:JWT的签名保证了数据的完整性,但它的Payload部分通常不加密。因此,敏感信息不应直接放在JWT的Payload中。为了保护数据,可以使用JWE(JSON Web Encryption)标准加密JWT的Payload。
- 密钥管理:签名的安全性依赖于密钥的保护。如果密钥泄露,攻击者可以伪造有效的JWT。因此,密钥管理是JWT安全的关键。
- Token泄露与防护:JWT通常会存储在客户端(如本地存储或Cookies中),如果JWT泄露(如通过XSS攻击),攻击者可以冒充合法用户。可以通过设置短期有效期(
exp
)和定期刷新Token来降低风险。
JWT与Session的对比
- 无状态认证:JWT通常用于无状态认证,即服务器不存储会话数据。相比之下,Session认证通常需要服务器存储用户的会话信息。
- 扩展性:由于JWT不依赖服务器存储,因此在分布式系统中更具扩展性。Session认证在多服务器环境中需要依赖共享存储或会话粘性(Session Stickiness),从而增加了系统复杂度。