处理到期/"记住我" JWT的功能

时间:2014-05-12 07:59:41

标签: web-services rest authentication jwt

从概念上讲,我非常喜欢JWT,因为它符合REST等无状态(没有状态保存服务器端,所有相关数据都包含在令牌中)。

我不确定:未连接时你将如何处理令牌到期(即"记住我"功能)?

网络上有关于JWT的新兴报道,但我找不到任何回答过期问题的人。

澄清:我不是问如何处理令牌即将过期,但是当令牌已经过期时(用户关闭网站/应用程序一段时间)该怎么做。我想到的最简单的解决方案是缓存用户的凭据,这是相当不安全的。

6 个答案:

答案 0 :(得分:7)

我不确定如果我遵循,但我会写出我的想法。

想象一下令牌作为酒店卡,您提前支付5天(记住我将在5天后到期)。我可以在5天内进入建筑物,车库,房间等,在这5天之后,它不再工作了。

令牌已过期时该怎么办?什么都没有。

想象一下,我支付了5天的费用,我有紧迫感,我回家了(口袋里有卡片)。酒店根本不在乎,当5天过去时,卡片只是一块无用的塑料,如果你试图在酒店使用它,它什么都不做。

回到web开发。如果您提供记住我的服务,您可以设置一个到期日,让我们说7天。只要用户拥有令牌,他就可以毫无问题地访问服务。如果他丢失了令牌,他需要再次登录。如果他使用令牌并且已经过期,他也需要再次登录。

如果他登录,他会获得一个令牌7天,如果他不再使用它,20天后他又来了,他需要再次登录,服务器会拒绝你的请愿,直到你做如此。

如果你在前端使用像角度这样的东西,我会做的就是在启动时检查令牌验证,这样你就可以获得良好的用户体验。

我对你的问题一无所知是为了缓解这个问题。

答案 1 :(得分:2)

您需要在客户端上保留JWT,以便在页面加载时可用,最安全的策略是仅使用HTTPS的cookie。这将在每次请求时将JWT发送到您的服务器,服务器可以检查令牌的有效性并在它过期时拒绝它。您如何处理到期时间取决于您拥有的Web应用程序的类型。

对于单页应用程序(例如Angular.js应用程序),您可能希望构建应用程序,以便在引导应用程序的其余部分之前向服务器发出初始请求。如果服务器发现此请求中的JWT已过期,则会发出401响应。您的应用程序将通过呈现登录表单来响应此响应。否则,它将继续假设JWT有效并可用于访问所需资源。如果应用程序在任何时候看到401,它应该将用户带回登录表单。

对于在服务器上呈现其页面的传统Web应用程序:对于任何具有过期JWT的请求(从cookie中读取),服务器应发出302重定向到登录表单。

答案 2 :(得分:2)

除了@Jesus answer之外,您还可以考虑实施刷新令牌系统:https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/

在酒店示例中,您的酒店卡(访问令牌)在时间X之后将无效,但在接待处您可以使用您的护照(刷新令牌)再次获得新的酒店卡。

您可以使用有关用户正在使用的设备的其他数据将刷新令牌存储在数据库中,以便在设备被盗时禁用该设备。

示例:

  1. 首先更正客户端登录:创建一个永久有效的刷新令牌(直到它被删除或失效)
  2. 在数据库中存储刷新令牌
  3. 返回访问令牌(JWT),其中包含到客户端的到期时间(此令牌未存储在数据库中)
  4. 对于下一个请求,客户端发送访问令牌

  5. 现在检查访问令牌是否已过期:

    5.1访问令牌未过期,一切正常

    5.2访问令牌已过期,检查数据库中是否有刷新令牌

    5.2.1刷新令牌在数据库中,返回新的访问令牌

    5.2.2数据库中没有刷新令牌,返回401 /注销,用户必须重新登录

  6. 希望这有帮助。

答案 3 :(得分:1)

对于在理论上如何实现“记住我”功能的既定问题,没有黑白答案。对于为什么不应该做某事,给出了许多理论上的论据,但与此同时,对于该问题的实际执行方式却没有明确的答案。

Remember-me隐含地带来了一个问题,即您需要更长的令牌到期时间窗口,这是无法解决的。最安全的方法是定期给用户短暂的到期时间;但是,实际上没有人喜欢它,因此进行了权衡,其中权衡了理论上的安全完善性和实际措施。

这种权衡的工作方式是修补令牌长期过期带来的不完善之处。但是,请不要误会,您将需要一个期限很长的jwt / cookie (无论您使用两个令牌,实现某种辅助刷新机制还是其他方法,最后都会遇到相同的问题)!
根据我读过的其他人如何做到的文章,这就是它的完成方式。

我将通过在用户检查“记住我”时对存储在httpOnly /安全cookie中的jwt提供3个月的有效期来实现此目的。
注销后,只需清除cookie。
显然在顶部使用https / CSRF措施进行保护。

如果您不同意它,请不要大惊小怪,并提供替代解决方案-很明显,我所阅读的无数讨论中都没有。
如果有直接解决问题的方法,那么一开始可能不会有太多讨论。

答案 4 :(得分:0)

我认为你问的是如何使JWT服务器端失效的长期令牌(例如“记住我”功能)?

我最近自己遇到了这个问题,并最终使用唯一的用户密码来使令牌无效,当用户尝试验证使用旧秘密生成的令牌时,它将失败。用户名可以在解码的JWT预验证中找到。

你可能甚至可以使用用户密码盐,这样当用户更改密码时,任何当前的JWT都会失效(假设你同时也更改了盐),这可能会有问题但是密码哈希和JWT将紧密耦合

答案 5 :(得分:0)

我可以想到一种方法,但它并没有真正定义标准。

如何为索赔添加另一种具有不同寿命的到期日期呢?对于两个声明,我们可以将其中较短的一个视为资源访问到期日期,将较长的一个视为刷新到期日期,例如

{
    "iat": /* current time */,
    "bbf": /* current time + 1 hour -- expired means no resource access */
    "exp": /* current time + 1 week -- expired means cannot refresh */
}

(注意:我使用bbf来缩短过期日期。没有具体原因,只因为它有3个字符。)

所以选中“记住我”,当用户重新连接时,他可以使用相同的令牌来请求新的,但不能访问资源。这样,所有相关数据都包含在令牌中 - 无需额外的令牌。

最后,当“记住我”没有选中时,只需对bbfexp使用相同的生命周期。

相关问题