我应该使用什么来对我的 Django Rest API 进行身份验证?

信息安全 验证 api jwt django
2021-08-24 00:15:09

我刚刚阅读了这篇关于 JWT 糟糕的原因的文章。我现在不确定应该使用什么进行身份验证。

对于上下文:我编写的 API 主要用于移动应用程序(iOS 和 Android)。将来它也将通过 React Frontend 访问。

过去我只是使用 DRF 的内置令牌身份验证。然后,手机只会将此令牌存储在相应应用程序的存储中。

现在我最近被告知,这不安全,我应该使用 JWT。在研究 JWT 时,我发现了上面的文章,其中详细说明了为什么 JWT 很烂,并且基本会话身份验证更好。但据我所知,当用作 API 时,我不能将会话身份验证与 DRF 一起使用,可以吗?

所以我的问题是?我应该使用 DRF 的哪些工具进行身份验证,以便安全?

2个回答

我是那篇文章的作者,也是我发表的关于为什么 JWT 糟糕且愚蠢的一些流行的技术演讲(所有这些 @joepie91 都雄辩地写得比我以往任何时候都好:http ://cryto.net /~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/)。

鉴于您的应用程序要求(移动应用程序 + 仅与后端 API 对话的 JS 前端应用程序),我建议您使用 OpenID Connect 授权代码流程(您的移动应用程序使用 PKCE)。

具体来说,对于您的移动应用程序,我建议使用出色的 AppAuth 库:https ://appauth.io/ (它具有适用于 iOS + Android 的出色库)。

现在,您可能想知道,当我公开呼吁人们反对使用 JWT 时,为什么我会推荐使用 OpenID Connect(以及 JWT):我会告诉您——对于大多数事情来说,这并不重要。

事情是这样的:是的,在构建安全应用程序时使用 JWT 非常糟糕。它们很复杂,目前大多数库的规范都不完整,使用 JWT 加密等更高级的功能几乎肯定会给您带来巨大的麻烦和服务之间的兼容性问题。

此外,JWT 在身份验证中变得流行的全部原因是它们经常用于缓存身份验证和授权数据——这整个做法在安全世界中是一个很大的 NO NO。

缓存敏感数据(如身份验证和授权数据)是您为安全所做的最糟糕的事情:您信任过时的信息。当前所有基于 JWT 构建的身份验证系统都存在这种幼稚问题。

一旦您陷入尝试使用 JWT 来“加速”您的站点/API 的兔子洞,您就已经犯了安全罪,现在处于危险之中。

此外,一旦人们开始使用 JWT 并意识到他们处于危险之中,他们就会尝试重新集中所有内容(正如另一位评论者所建议的那样)并开始使用撤销列表,以便他们可以在发生坏事时撤销令牌。这会导致与传统会话管理相同的速度损失,但由于 JWT 比会话 cookie“更重”且更脆弱,因此速度损失更大。

很抱歉咆哮,但这是我的建议:

  • 如果你想要真正的安全,你必须使用服务器端会话。在您的情况下,这将需要支持来自您的 API 后端的会话 cookie,以便当您的反应应用程序向您的 API 进行身份验证时,API 会设置一个安全 cookie,反应应用程序每次与 API 服务对话以进行身份​​验证时都会自动使用该 cookie。您还需要在您的移动应用程序中使用基于 cookie 的 API(我不熟悉构建原生移动应用程序,因此无法对此组件发表评论)。
  • 如果您想要简单性和与几乎所有其他主要 Web 应用程序相同的安全性,请使用 OIDC 并使用开箱即用的开源解决方案。这是目前最简单的方法,虽然它并不完美,但如果它解决了您的问题,那么它可能没什么大不了的。

如果您正在构建一些敏感的东西,请尽可能尝试使用服务器端会话 cookie。否则?不要担心细节,顺其自然。

您有两个不错的选择 IMO:

  1. 使用随机字符串,这将与存储在数据库中的会话相对应。如果可能,这是最好的选择。虽然这些会议不应该是长期的。如果您需要长期登录,请使用 JWT 令牌进行重新身份验证。
  2. 使用使用对称密钥 (HMAC) 签名的 JWT。这更快,同时仍然安全。但是,此选项对带宽的要求仍然更高,并且通常比随机字符串要慢。