停止使用 JWT
争论范围
- 大多数参与者区分了两种主要用例:
- 基于浏览器的用户会话。
- 服务到服务 / 后端令牌。
- 广泛的温和共识:JWT 往往不适合浏览器会话,但在后端和联合身份场景中可以很好,甚至是理想选择。
用于基于浏览器的会话的 JWT
- 批评者说,与放在 HttpOnly cookie 中的简单不透明会话 ID 相比,JWT 增加了复杂性;如果同一台服务器既签发又验证它们,就没有实际收益。
- 提出的主要痛点:
- 很难/很别扭地撤销和退出登录,尤其是按设备退出登录。
- 可重放性和长寿命令牌。
- 倾向于把敏感或可变数据塞进令牌里,从而带来缓存失效和安全问题。
- 有人认为:如果你本来就需要一个数据存储(用于用户、权限),那就直接把会话状态存在那里,避免为会话使用密码学。
安全属性与实现陷阱
- 历史问题:
alg=none、算法降级/混淆、库把公钥当作 HMAC 密钥接受、默认值不佳。 - 有人认为这些是库的 bug,而且大多已经修复;其他人则说,这些问题源于一个鼓励踩坑和复杂性的规范。
- 对如今 JWT 到底有多“不安全”存在分歧:
- 一派:“如果你限制算法并使用好库,JWT 是没问题的。”
- 另一派:“规范鼓励误用;CVE 仍在不断出现;更安全的设计已经存在。”
撤销、“无状态”认证与退出登录
- 核心张力:JWT 被宣传为“无状态”,但安全的退出登录和被攻破后的处理需要状态:
- 撤销列表 / 黑名单。
- 按用户的“早于某时间均无效”时间戳。
- 密钥轮换方案。
- 有人认为,一旦你加入这些状态,你就失去了相对于传统会话的主要优势。
- 也有人反驳说,撤销列表比完整会话存储小得多,而且更容易在全局复制。
Cookie、存储,以及 XSS/CSRF
- 强烈支持在浏览器会话中使用 HttpOnly、Secure、SameSite cookie。
- 许多人警告不要把 JWT 存在 localStorage 中,因为会被 XSS 窃取;有些人认为如果你“根本不允许不可信 JS”那问题不大,另一些人则认为这不现实。
- 有观点指出,HttpOnly 可以防止令牌被盗,但不能阻止由 XSS 驱动的滥用。
替代方案与更广泛的生态
- 提到的替代方案包括:不透明随机令牌、签名 cookie、PASETO、macaroons、SAML/OIDC 模式、自定义方案。
- 有人称赞 PASETO/macaroons 的设计更能抵抗误用,但指出生态和采用度有限。
- 还有几位认为“停止使用 JWT”这一说法过于夸张或像标题党;他们更倾向于“有针对性且谨慎地使用 JWT”。