如何在身份验证中使用 JWT?

Posted

技术标签:

【中文标题】如何在身份验证中使用 JWT?【英文标题】:How to use JWT in auth? 【发布时间】:2019-04-03 12:35:13 【问题描述】:

我最近决定查看当前的身份验证流程和可用解决方案。简单来说,有 2 个选项我感兴趣:Sessions/CookiesJWT

让我们检查第一个。 Sessions 是“古老而黄金”的技术,目前仍在广泛用于大多数基于服务器的应用程序。

会话/Cookie 的优势

易于使用 加密 防止 XSS 攻击(带有httpOnly 标志) 防止 CSRF 攻击(带有sameSite 标志) 轻松设置过期时间 通过设置适当的标头从服务器端轻松管理 可以使用会话存储(例如 redis)进行扩展

缺点

小尺寸 (4kb) 用于基于服务器的应用程序,不适合 SPA(单页应用程序) 跨域请求问题 由于许多应用可以使用单一 API,因此很难通过会话管理身份验证 SSO(单点登录) - 如何实施? 需要额外的服务器来存储会话数据 需要为每个请求查询数据库(检查用户 ID)

所以在现代世界,JWT 来解决这些问题。

智威汤逊的优势

天生安全 无状态,适用于任何平台(网络、移动) 最适合 Restful API 广泛用于 SSO(单点登录) 无需在服务器端查询数据库(检查用户 ID),因为令牌可以包含不可变数据 可以在各方之间安全地传输数据,因为不可能伪造数据

缺点

尺寸更大 不容易从服务器端管理 需要从客户端手动发送标头

经过大量阅读该主题后,我仍然无法弄清楚如何正确处理 JWT。我们来谈谈客户端以及如何存储 JWT。

我猜,大多数人发现将 JWT 存储在 localStorage 中很容易,但这当然是个坏主意,因为它不安全且易受 XSS 攻击。饼干? - 可能,我认为,只是没有设置会话的 cookie,但必须与跨域请求作斗争并且不会受到 CSRF 的攻击。你知道实现这一目标的正确方法吗?我还有一个大问题 - 在哪里存储?

另一方面,假设我们有 SPA,它现在很流行。来自Auth0 documentation

单页应用程序

如果您有一个没有相应后端服务器的单页应用程序 (SPA),则您的 SPA 应在页面加载时请求新令牌并将它们存储在内存中,而无需任何持久性。为了进行 API 调用,您的 SPA 将使用令牌的内存副本。

这是否意味着我必须在每次页面刷新时登录并获取令牌? - 来吧,这不是办法。我希望用户保持登录状态。

那么回到带有会话/cookie 的服务器端常规 Web 应用程序?我个人更喜欢 JWT,那么使用 JWT 的最佳方式/流程是什么?我将不胜感激任何明确的解释。谢谢!

【问题讨论】:

【参考方案1】:

JWT 本质上并不安全。这不是一个好的或安全的标准。 http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/

关于如何让用户在 SPA 上保持登录状态,您可以使用会话。将会话密钥存储在 cookie 中,然后在加载页面时向后端发送 REST API 调用以加载用户/会话数据。

或者,使用身份验证流程,在用户加载应用程序时将用户重定向到 ID 服务器。然后,ID 服务器可以设置 cookie,并管理身份验证,而无需用户再次登录。这类似于您询问的 SPA 解决方案,但用户不会注意到太多。

【讨论】:

以上是关于如何在身份验证中使用 JWT?的主要内容,如果未能解决你的问题,请参考以下文章

Grafana:如何使用 JWT 身份验证?

如何在 KONGO 中设置 JWT 身份验证

如何使用护照身份验证更新包含 jwt 的 cookie

我们如何在同一个 Spring 应用程序中同时添加 JWT 和基本身份验证? [关闭]

如何允许任何用户使用 Laravel JWT 身份验证访问路由?

如何在 Python 中使用 JWT 实现基于角色的身份验证