Django SimpleJWT:令牌认证的一些问题

Django SimpleJWT: Some questions with token authentication

我正在使用 SimpleJWT 在 Django 中实现身份验证,对此有几个问题。为了提供一些背景知识,我的后端有多个域,一些使用普通登录(用户名和密码),一些使用 SSO 登录。

问题 2: 假设,我将访问令牌存储在本地存储中并将访问令牌发送到所有 API,并且我也在它过期之前刷新它。但是如果用户关闭浏览器会发生什么,我们无法刷新访问令牌。访问令牌过期并且用户被注销。我们如何让用户保持登录一段时间(比如 30 天)?

对于问题 2,将此代码添加到您的 settings.py 文件中

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(days=30),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=30),
}

当访问令牌过期时,您使用刷新令牌获取新的访问令牌。

之所以可行,是因为刷新令牌的寿命很长,通常长达 30 天(但如果您愿意,可以更长)。

示例:

  • 用户关闭浏览器
  • 10天后回来
  • 用户向服务器发送请求
  • 服务器将return 401 Unauthorized response because Access token has expired
  • 您的应用将发送请求以使用刷新令牌获取新的访问令牌
  • 如果刷新令牌有效,服务器将return一个新的访问令牌
  • 如果刷新令牌过期,服务器将return 401 响应。这意味着用户需要重新登录。

安全考虑

就个人而言,我认为 JWT 对于大多数网络应用程序来说不是一个合适的想法,因为关于如何安全存储令牌的意见和建议相互矛盾。

由于Refresh token功能强大,不建议保存在浏览器中。 那么你把它存储在哪里? 那时这种由 JWT 提供支持的“无后端”网络服务的误导性想法开始瓦解。

关于存储代币的悖论:

  1. 存放在localstorage:易受XSS攻击
    这真的很严重,因为 XSS 漏洞也可能来自第三方 JS 库,而不仅仅是来自您自己的代码。 Hackers can hijack a third-party library on NPM to inject malicious code 并且你可能在你的项目中不知不觉地使用它(它可能是另一个依赖项的依赖项的依赖项......)。

  2. Store it in httponly cookies: 免受XSS攻击但需要第一方后端服务器(因为第三方认证服务器不能设置cookies对于另一个域)。
    如果您停下来想一想,您会注意到这种情况与常规会话身份验证完全相似,其中会话令牌保存在 cookie 中。那么,为什么不使用会话身份验证而不是这种复杂的 JWT 设置呢?

我建议您彻底研究这个问题,然后决定您的 Web 应用程序是否真的需要 JWT。


使用跨源 cookie 的 JWT 身份验证

既然你提到你的前端应用程序连接到另一个域中的 API 服务器,那么使用 JWT 似乎没问题。

如果您控制 API 服务器,您可以设置 CORS headers 以允许 API 服务器在您应用程序的域上设置 cookie。

Important:
Since this involves Cookies, it is vulnerable to CSRF attacks. But > that is easier to prevent using CSRF tokens. That means, with every POST request, you'll need to send CSRF token and the API server must also validate that CSRF token

这是我在这种情况下制作的授权流程图: