63

我读到在使用 JWT 时,无需防范 CSRF 攻击,例如:“由于您不依赖 cookie,因此您无需防范跨站点请求”。

但是,我不明白的是:如果我将令牌存储在(正如我在同一网站的教程中localStorage被告知的那样),什么可以防止攻击者通过读取我的而不是我的 cookie 来伪造恶意请求?localStorage

由于它是在服务器端生成的,因此我不知道如何将令牌用于客户端请求,而无需将其存储在客户端的某个位置。

4

2 回答 2

145

严格来说,是的,存储在本地/会话存储(我称之为 HTML5 存储)中的任何内容都可能在跨站点脚本 (XSS) 攻击中被盗。见这篇文章

然而,有很多活动部件需要考虑。

首先,HTML5 存储和 cookie 在 JavaScript 访问范围内的范围存在细微差别。

HTML5 存储是:

  • 分为http和https。在http://example.comHTML5 存储中运行的 JavaScript 无法访问存储在https://example.com.
  • 在子域之间划分。http://example.com运行在其上的 JavaScript 无法访问存储在 HTML5 存储中的项目http://sub.example.com(但是,您可以采取一些技巧来解决这个问题)。

饼干更松散:

  • 带有域的 cookieexample.com将同时发送到两者http://example.comhttps://example.com 除非它具有属性secure,在这种情况下,它只会发送到https.
  • 未使用显式域发送的 cookie 只会被发送回发送它的确切域。如果域被明确定义为example.com,那么它将被发送到example.comsub.example.com。(不幸的是,这是 cookie “规范”中最令人困惑的部分,请参阅这篇文章)。
  • secure如果 cookie 在具有匹配域(并尊重cookie 标志)的页面上运行,则 cookie 可以被 JavaScript 读取,除非cookie 具有httpOnly属性,在这种情况下 JavaScript 将无法读取它。

其次,由于 cookie 带有域标记,因此当向服务器发出请求时,浏览器将发送具有匹配域的全部和唯一的 cookie,而不管发起请求的页面的域是什么

最后一部分是 CSRF 攻击是如何完成的(同源策略只能起到这么大的作用)。CSRF 上的OWASP 页面是了解此类攻击如何工作的好资源。

将身份验证令牌存储在本地存储中并手动将其添加到每个请求以防止 CSRF 的原因是关键字:手动。由于浏览器不会自动发送该身份验证令牌,因此如果我访问evil.com并且它设法发送 a POST http://example.com/delete-my-account,它将无法发送我的身份验证令牌,因此该请求将被忽略。

考虑到上述情况,是否使用 cookie 或 HTML5 存储成为一系列权衡:

将 authen 令牌存储在 HTML5 存储中意味着:

  • (-)在 XSS 攻击中被盗的风险。
  • (+)提供 CSRF 保护。
  • (-)必须手动修改发送到服务器的每个请求,将您限制为 SPA(例如 AngularJs)Web 应用程序。

另一方面,如果您将身份验证令牌存储在标记为httpOnly and secure的 cookie 中,则:

  • (+)Authn 令牌不能被 XSS 窃取。
  • (-)您必须自己提供 CSRF 保护。在某些框架中实现 CSRF 保护比其他框架更容易。

哪个选项更好取决于您的需求。

  • 您的身份验证令牌是否保护与金钱有关的任何事情?您可能需要 cookiehttpOnly secure选项。
  • 实施 CSRF 保护所需的努力程度是否不值得它保护的资产?那么 HTML5 存储可能是正确的地方。
于 2016-02-11T18:17:27.270 回答
2

使用基于令牌的身份验证时,您必须手动将令牌与请求关联。与 cookie 不同,浏览器不会自动设置令牌,因此不易受到csrf攻击。

虽然这种方法可以免受csrf攻击,但它很容易受到xss攻击。

一个最小的改进是使用session storage而不是local storage因为session storage数据在用户关闭选项卡/浏览器后被清除。

于 2018-10-03T08:02:59.667 回答