发布于 2026-01-05 0 阅读
0

前端客户端(GraphQL)处理 JWT 的终极指南

前端客户端(GraphQL)处理 JWT 的终极指南

这是发表在blog.hasura.io上的一篇原创文章的节选。

JWT(JSON Web Token,发音为“jot”)正逐渐成为一种流行的身份验证方式。本文旨在揭开 JWT 的神秘面纱,探讨其优缺点,并介绍在客户端实现 JWT 的最佳实践,同时兼顾安全性。文中的示例尤其适用于 GraphQL 客户端。

引言:什么是 JWT?

有关 JWT 的详细技术说明,请参阅本文

在身份验证中,JWT 是由服务器颁发的令牌。该令牌包含一个 JSON 有效负载,其中包含特定于用户的信息。客户端在与 API 通信时(通过将其作为 HTTP 标头发送)可以使用此令牌,以便 API 能够识别令牌所代表的用户,并执行针对该用户的特定操作。

但是客户端难道不能创建一个随机的 JSON 数据来冒充用户吗?

问得好!这就是为什么 JWT 也包含签名的原因。这个签名由颁发令牌的服务器(例如您的登录端点)创建,任何其他接收到此令牌的服务器都可以独立验证该签名,以确保 JSON 有效负载未被篡改,并且包含的​​信息确实来自合法来源。

但是,如果我有一个有效且已签名的 JWT,而有人从客户那里窃取了它,他们岂不是可以永远使用我的 JWT 吗?

是的!如果 JWT 被盗,窃贼仍然可以继续使用它。接受 JWT 的 API 会进行独立验证,不依赖于 JWT 的来源,因此 API 服务器无法判断该令牌是否被盗!这就是为什么 JWT 需要设置过期时间。而且这些过期时间通常设置得很短。常见的做法是将其设置为 15 分钟左右,这样任何泄露的 JWT 都会很快失效。但同时,也要确保 JWT 不会泄露。

因此,千万不要将 JWT 存储在客户端,例如通过 cookie 或 localStorage。这样做会使您的应用程序容易受到CSRFXSS攻击,恶意表单或脚本可以利用或窃取存储在 cookie 或 localStorage 中的令牌。

那么,JWT 是否有特定的结构?它的结构是什么样的?

序列化后的 JWT 看起来像这样

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.XbPfbIHMI6arZ3Y922BhjWgQzWXcXNrz0ogtVhfEd2o

如果解码该 base64,您将得到由 3 个重要部分组成的 JSON:标头有效负载签名

序列化后的形式如下:

[ base64UrlEncode(header) ] . [ base64UrlEncode(payload) ] . [signature ]

JWT 本身并未加密。它采用Base64 编码签名。因此,任何人都可以解码该令牌并使用其中的数据。JWT 的签名用于验证其来源是否合法。

下图简要展示了如何颁发 JWT /login,以及如何使用 JWT 向另一服务发起 API 调用/api

哎!这看起来好复杂。为什么我不能继续使用传统的会话令牌呢?

这是互联网上一个令人头疼的话题。我们的简短(且带有个人观点)回答是,后端开发人员喜欢使用 JWT 的原因是:a) 支持微服务;b) 不需要集中式令牌数据库。

在微服务架构中,每个微服务都可以独立验证从客户端收到的令牌是否有效。微服务还可以进一步解码令牌并提取相关信息,而无需访问集中式令牌数据库。

这就是为什么 API 开发者喜欢 JWT,而我们(客户端)需要弄清楚如何使用它。但是,如果你可以使用你最喜欢的单体框架颁发的会话令牌,那就完全没问题了,可能根本不需要 JWT!

点击此处继续阅读

文章来源:https://dev.to/hasurahq/the-ultimate-guide-to-handling-jwts-on-frontend-clients-graphql-252a