JSON Web 令牌过期和记住我功能

Posted

技术标签:

【中文标题】JSON Web 令牌过期和记住我功能【英文标题】:JSON Web Token expiration and remember me functionality 【发布时间】:2017-04-26 17:07:22 【问题描述】:

我开始使用 django-rest 框架作为后端的 Angular 2 单页应用程序的身份验证系统。我还想要某种“记住我”功能,让用户在一定时间内保持登录状态。

从我目前阅读的内容来看,这种 Angular 2 SPA/REST API 的最佳身份验证方法似乎是使用 jwt(json Web 令牌)。对于 jwt 身份验证,我查看了 django-rest-framework-jwt (https://github.com/GetBlimp/django-rest-framework-jwt)。

我看到的问题是令牌需要有很短的生命周期(几分钟到几个小时......),以便在令牌被盗时最大限度地减少安全问题。令牌现在需要经常刷新,以避免用户在使用应用程序时断开连接。在这种情况下,“记住我”功能会带来问题,因为令牌的生命周期很短。

我想到了一个解决方案,其中涉及将用作刷新令牌的第二个令牌。它将是不透明的,具有更长的寿命,并且将包含特定于用户的信息(IP 地址或类似的东西),因此如果它被盗,特定于用户的不同信息将使此刷新令牌无效。

以下是我的问题

1- 我想知道它们是否是解决此问题的现有解决方案。对于任何安全/身份验证问题,我更愿意依靠经过良好测试的解决方案来避免我的 API 受到损害。 2- 基于特定用户信息的刷新令牌是个好主意吗? 3- 还有什么其他想法可以实现我想要的吗?

【问题讨论】:

记住我功能是可选的还是所有用户都没有选择? @JJB 最后,我希望“记住我”功能是可选的。但第一步,所有用户都可以。 我对 django-rest-framework-jwt 本身不太确定,你能选择 JWT 中存储哪些数据吗?您可以让它返回 2 个不同的刷新令牌: REMEMBER ME 版本 如果在登录时选择了记住我,您将返回一个过期时间更长的刷新令牌,还包括 JWT 中的其他数据,如您所说的 IP 甚至浏览器指纹。您将需要一种方法来撤销刷新令牌。 NONE REMEMBER ME 版本刷新令牌将返回一个短暂的过期时间。 会话 cookie 非常类似于令牌,但它们已内置到期并随 Django 一起提供。最好只使用 Django 会话而不是令牌。 @RossRogers 我曾考虑过使用 Django 会话,但我计划将相同的 Rest-API 用于移动应用程序。我没有对此主题进行大量研究,但似乎 Django 会话不适用于移动应用程序。但是,是的,使用会话将是解决我的问题的一个很好的临时解决方案...... 【参考方案1】:

对于您的情况,您确实需要一种存储已发行令牌的方法。

我总是使用 OAuth2.0 服务器设置来管理身份验证并返回令牌 OAuth 设置使用数据库来管理所有内容,因此很容易管理和撤销令牌。

数据库架构将是这样的http://imgur.com/a/oRbP2,如果只使用 JWT 而不对已发出的长期过期令牌进行任何管理,您就会遇到无法轻松撤销的安全问题。

我建议不要在 JWT 中包含任何诸如密码之类的东西,并要求他们更改密码,如果他们在任何地方都使用该密码,那么他们将不得不在任何地方进行更改。

从 cmets 更新

Sessions Authentication 使用 session_id,它大部分时间都存储在 cookie 中,并附加到每个传出请求。它是有状态的。它只不过是与服务器在内存/数据库中的用户帐户相关联的唯一标识符。例如,这可能会在扩展基础架构时运行多个服务器/实例时出现问题。

令牌认证服务器上没有持久化会话,因此这意味着它是无状态的。它通常使用标头 Authorization: Bearer REPLACE-WITH-TOKEN 。这意味着此令牌可以传递到多个不同的服务器/实例,因为身份验证不限于您启动身份验证的服务器。这有助于扩展您的基础架构。令牌也可以传递给其他客户端。

RESTful API 是无状态的,因此服务器上不能存储会话状态。相反,它必须完全由客户端处理,这就是使用令牌身份验证的原因。

我在尝试将 JWT 用于需要比 JWT 设计用途更多的应用程序时遇到了确切的问题。 OAuth2.0 有更多选项,我认为这些选项对于以最安全的方式满足您的要求是必要的,甚至还有一些您可能会在未来发现非常有用的功能,因为您的应用程序可能会增长并需要更多有关身份验证的功能。

【讨论】:

我之前看过OAuth2框架。有一个用于 django rest 的包(github.com/evonove/django-oauth-toolkit>)。但它只使用令牌而不使用 JWT。这个解决方案会不会有点类似于RossRogers在之前的cmets中提出的会话解决方案?不同之处在于会话令牌存储为 cookie,而 OAuth 令牌存储在我们想要的位置(本地存储或 cookie)..? 对不起,我在 OAuth 上下文中放错了 JWT,它应该只是说令牌。我现在会更新它并回答你的其他问题。 感谢您的详细解答!

以上是关于JSON Web 令牌过期和记住我功能的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 DRF JWT 实现记住我的功能?

Laravel 4记住我过期时间

为啥要记住我的令牌?

Laravel 5.3记住我身份验证问题

Laravel 5.3记住我身份验证问题

如何设置 json web 令牌过期和验证