在基于Web的应用程序中,如何正确安全地存储JWT令牌?

43

我熟悉Web Storage APIs和cookies,但无法确定存储认证令牌的最安全方式。我想知道这是否会影响任何第三方库。

我希望能够获得一份详尽的可用方法列表,包括每种方法的优缺点以及最佳方式(如果有的话)。

3个回答

45

在哪里存储您的JWT

使用基于令牌的身份验证,您可以选择在哪里存储JWT。我们强烈建议您将令牌存储在本地存储/会话存储或Cookie中。

Web Storage(本地存储/会话存储)

通常,JWT存储在浏览器的本地存储中,在大多数情况下都可以很好地工作。

当使用用户名和密码登录用户时,响应正文包含access_token JWT。然后,您需要在客户端代码中处理此响应。该令牌可以存储在localStorage或sessionStorage中。

单击此处以查看使用sessionStorage的示例

localStorage和sessionStorage均扩展自Storage。它们之间的唯一区别在于数据的持久性:

localStorage - 数据持久存在,直到显式删除为止。所做的更改保存并对站点的所有当前和未来访问者可用。

sessionStorage - 所做的更改保存并对当前页面以及同一窗口中以后访问站点的访问者可用。关闭窗口后,存储将被删除。

Web Storage的缺点

  • 与Cookie不同,本地存储仅限于特定域,并且其数据不能被任何其他域(包括子域)访问。
  • Web Storage可以通过在同一域上运行的JavaScript访问,因此您站点上运行的任何JavaScript都可以访问Web Storage,并且因此容易受到跨站脚本(XSS)攻击的影响。
  • 开发人员必须确保JWT始终通过HTTPS发送,而永不通过HTTP。

使用Cookie

您还可以使用Cookie存储JWT。设置Cookie的确切方式取决于您使用的客户端语言。

有不同的选项来控制Cookie的生存期:

  • 会话 Cookie 可以在浏览器关闭后销毁。
  • 实现服务器端检查(通常由使用的 Web 框架为您完成),并且可以实现过期或滑动窗口过期。
  • 可以使用过期时间使 Cookie 持久化(在浏览器关闭后不被销毁)。
  • 如果设置了 httpOnly 标志,Cookie 可以被 JavaScript 和服务器端代码都读取,或仅允许服务器端读取。

Cookie 缺点

  • Cookie 的最大大小仅为 4KB,因此如果您附加到令牌上的声明很多,可能会造成问题。
  • Cookie 可能受到跨站请求伪造(CSRF 或 XSRF)攻击的影响。这种类型的攻击发生在恶意网站导致用户的 Web 浏览器执行未经授权的操作的可信站点上,而用户当前已经进行了身份验证。这是对浏览器处理 Cookie 的一种利用。使用 Web 应用程序框架的 CSRF 保护使得 Cookie 成为存储 JWT 的安全选项。还可以通过检查 HTTP 的 RefererOrigin 标头来部分预防 CSRF 攻击。
  • 如果应用程序需要跨域访问,则可能很难实现。Cookie 具有其他属性(Domain/Path),可以修改这些属性以允许您指定 Cookie 可以发送到的位置。

原始文章:https://auth0.com/docs/security/store-tokens#how-to-implement


2
你好,我喜欢你的回答。还有一个问题,关于这个:“与 cookie 不同,本地存储被限制在特定域中,并且其数据不能被任何其他域访问,包括子域。”你能提供一个例子吗?这在实践中意味着什么? - GeraltDieSocke

12
  1. JWTs不应存储在您的localStorage中
  2. 实际上,它们甚至不应存储在您的cookies中,除非您能够实现非常严格的CSRF保护

查看此处以获取动机

  • 将JWT作为id_token就像是您的用户凭证
  • 将JWT作为access_token就像是您的会话令牌

最安全的选项是在内存中存储查看此处以深入了解


32
问题询问关于在哪里存储JWT令牌,但是你的回答只说明了不应该将JWT存储在哪里并提供了一些链接。回答应该是自我完备的,如果链接中有答案,最好将那些信息引入到你的回答中。 - giraffesyo
3
@giraffesyo 答案在最后一行:“最安全的选项是内存中的”。 - Tomasz Gawel
据我所了解,内存存储似乎只适用于单页应用程序。 - undefined

0
如果@dmitry-s的解决方案对您仍然无效,考虑按照this article的建议将访问令牌存储在Web Worker中。
Web Worker拥有自己的线程,不会给恶意的第三方或XSS脚本获取令牌的机会(就像localStorage和sessionStorage一样)。但请注意,您需要设计前端代码与Web Worker安全通信的方式,以便安全地进行API请求。
它在现代浏览器中广泛使用,但您可以在here检查它是否适用于您的用户。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接