【问题标题】:Should JWT be stored in localStorage or cookie? [duplicate]JWT 应该存储在 localStorage 还是 cookie 中? [复制]
【发布时间】:2016-04-21 10:24:15
【问题描述】:

为了使用 JWT 保护 REST API,根据一些资料(例如 guidequestion),JWT 可以存储在 localStorageCookies 中。根据我的理解:

  • localStorage 受到 XSS 攻击,一般不建议在其中存储任何敏感信息。
  • 通过 Cookies,我们可以应用标志“httpOnly”来降低 XSS 的风险。但是,如果我们要在后端从 Cookie 中读取 JWT,我们就会受到 CSRF 的影响。

所以基于上述前提——我们最好将 JWT 存储在 Cookies 中。在对服务器的每个请求中,都会从 Cookie 中读取 JWT,并使用 Bearer 方案将其添加到 Authorization 标头中。然后,服务器可以验证请求标头中的 JWT(而不是从 cookie 中读取它)。

我的理解正确吗?如果是这样,上述方法是否有任何安全问题?或者实际上我们可以一开始就使用 localStorage?

【问题讨论】:

  • @lrn2prgrm 不应同时使用(无状态)JWT (有状态)会话语义。
  • @corlaez 我正在使用 JWT,我计划在服务器端使用身份验证标头“Bearer mytoken”来验证我的 jwt。我的困惑是:如果我在第一次登录时使用 httpOnly 标志在 cookie 中发送原始 jwt(从服务器发送到浏览器),我如何从客户端提取 jwt 以放入我的 Authentication 标头以进行后续请求?难道 httpOnly 标志不允许我从客户端的 cookie 中提取信息吗?

标签: security cookies local-storage jwt restful-authentication


【解决方案1】:

我喜欢@pkid169 说的文章中提到的XSRF Double Submit Cookies 方法,但是有一点文章没有告诉你。您仍然没有受到 XSS 的保护,因为攻击者可以做的是注入脚本来读取您的 CSRF cookie(不是 HttpOnly),然后使用此 CSRF 令牌向您的 API 端点之一发出请求,并自动发送 JWT cookie。

所以实际上你仍然容易受到 XSS 的影响,只是攻击者无法窃取你的 JWT 令牌供以后使用,但他仍然可以使用 XSS 代表你的用户发出请求。

无论您将 JWT 存储在 localStorage 中,还是将 XSRF 令牌存储在非 http-only cookie 中,XSS 都可以轻松获取两者。甚至您在 HttpOnly cookie 中的 JWT 也可以被高级 XSS 攻击获取。

因此,除了双重提交 Cookie 方法之外,您还必须始终遵循针对 XSS 的最佳做法,包括转义内容。这意味着删除任何会导致浏览器执行您不​​希望它执行的操作的可执行代码。通常这意味着删除 //

【讨论】:

  • 您能否说明如何获取 HttpOnly cookie 中的 JWT?如果 XSRF 令牌被 XSS 破坏,它可以被 XSRF 使用,但它真的可以自己抢吗?
  • 我知道这是一篇旧帖子,但我想问一些问题...这是否意味着精心设计的脚本可以同时读取 localStorage 和 cookie?如果是这样,是否可以假设无论我们将 JWT 存储在浏览器的哪个位置都可能被盗?然后,我觉得完全依赖 JWT 风险很大。
  • "即使您在 HttpOnly cookie 中的 JWT 也可以被高级 XSS 攻击获取。"是假的。编辑原始帖子以更正此问题。
  • “即使你在 HttpOnly cookie 中的 JWT 也可以被高级 XSS 攻击抓取” 我可以想象有人通过将 cookie 发送到他自己的服务器来抓取它。为此,他可以使用具有适当值的凭据标志的 fetch。这里的主要问题是 CORS 保护,但在某些情况下我认为这是可能的。
  • "inject script that read your CSRF cookie (which is not HttpOnly)" Html.AntiForgeryToken() 在 ASP.NET MVC 中的默认实现使用 HttpOnly cookie 作为 CSRF 令牌。我认为您仍然容易受到某些 XSS 的影响,但认为这值得一提。
【解决方案2】:

及时的post from Stormpath 非常详细地阐述了我的观点并回答了我的问题。

TL;DR

将 JWT 存储在 cookie 中,然后像我提到的那样在每个请求的 Authorization 标头中传递 JWT,或者如文章建议的那样,依靠后端来防止 CSRF(例如,在 Angular 的情况下使用 xsrfToken )。

【讨论】:

  • 您好,我不确定这是否正确,但是当您为控制器实现 CrossOrigin 时,使用 cookie 存储 jwt 是否有一些特别的缺点,这是我的服务器应用程序所在的场景一个不同的地方,我们在位于另一个城市的客户端应用程序中从它调用 api?这难道不是很多网络服务提供商不使用 cookie 的原因吗?
  • CrossOrigin 并不意味着物理位置。它指的是来自其他域的请求。在 .net 核心中,当您决定使用 CORS 时,您可以指定要允许的域;您将允许哪些标题,等等。
【解决方案3】:
  • 不要将令牌存储在 LocalStorage 或 SessionStorage 中,因为此类令牌可以从 javascript 中读取,因此容易受到 XSS 攻击。
  • 不要将您的令牌存储在 Cookie 中。 Cookie(带有 HttpOnly 标志)是一个更好的选择 - 它容易受到 XSS 攻击,但容易受到 CSRF 攻击

相反,在登录时,您可以传递两个令牌:访问令牌和刷新令牌。访问令牌应存储在 Javascript 内存中,刷新令牌应存储在 HttpOnly Cookie 中。刷新令牌仅用于并且仅用于创建新的访问令牌 - 仅此而已。

当用户打开新标签页或站点刷新时,您需要根据存储在 Cookie 中的刷新令牌执行请求以创建新的访问令牌。

我也强烈推荐阅读这篇文章:https://hasura.io/blog/best-practices-of-using-jwt-with-graphql/

【讨论】:

  • 当您可以将刷新令牌视为访问令牌时,为什么会增加复杂性?考虑到我将访问令牌标记为securesamesite: stricthttp-only,这种方法如何更安全?
  • 不是更安全
  • 如果您的页面中有恶意 XSS,该脚本可以向 /refresh-token 发出 GET 请求并访问新的 jwt,然后将其发送到远程服务器。那么,在这种情况下,这个 schema 是否存在与 localstorage 相同的漏洞?
  • Why the added complexity when you can just treat the refresh token as an access token? @CharmingRobot 您如何使访问令牌无效?如果没有刷新令牌,您的访问令牌应该有很长的生命周期,因此用户不需要每 5 分钟登录一次。这就是存在刷新令牌的原因,因此用户可以注销从您的数据库中删除刷新令牌,并且访问令牌将在几分钟内过期。这就是存在刷新令牌的原因。
【解决方案4】:

为帮助防止利用现有 cookie 的 CSRF 攻击,您可以使用 SameSite 指令设置您的 cookie。将其设置为laxstrict

这仍然是 a draft,截至 2019 年是 not fully supported by all current browsers,但根据您数据的敏感性和/或您对用户使用的浏览器的控制,这可能是一个可行的选择。使用SameSite=lax 设置指令将允许“使用‘安全’...HTTP 方法的顶级导航。”

【讨论】:

    猜你喜欢
    • 2015-09-01
    • 2012-07-04
    • 2019-03-27
    • 2012-03-17
    • 2019-10-20
    • 2014-01-25
    • 2019-03-20
    • 1970-01-01
    相关资源
    最近更新 更多