问题描述
我读到使用 JWT 时,无需防范 CSRF 攻击,例如:"因为您不依赖 cookie,所以您不需要防止跨站点请求".
I read that when using JWT, there is no need to protect against CSRF attacks, for instance: "since you are not relying on cookies, you don't need to protect against cross site requests".
但是,有些我不明白:如果我将令牌存储在 localStorage 中(正如我被告知的那样同一个网站的教程),是什么防止攻击者通过读取我的 localStorage 而不是我的 cookie 来伪造恶意请求?
However, something I do not understand: if I store the token in localStorage (as I was advised on a tutorial of the same website), what prevents an attacker to forge a malicious request by reading my localStorage instead of my cookies ?
由于它是在服务器端生成的,我不知道如何将令牌用于客户端请求而不将其存储在客户端的某处.
Since it was generated on the server side, I don't get how I could use a token for a client request without it being stored somewhere on the client.
推荐答案
严格来说,是的,存储在本地/会话存储(我将其称为 HTML5 存储)中的任何内容都可能在跨站点脚本 (XSS) 中被窃取攻击.请参阅这篇文章.
Strictly speaking, yes, anything stored in local/session storage (which I'll call HTML5 Storage) could be stolen in a cross-site scripting (XSS) attack. See this article.
然而,有很多活动部件需要考虑.
There are a lot of moving parts to consider, however.
首先,HTML5 存储和 cookie 的范围在 JavaScript 访问方面存在细微差别.
First, there are subtle differences in how HTML5 Storage and cookies are scoped with respect to JavaScript access.
HTML5 存储是:
- 分为http和https.在
http://example.com
上运行的 JavaScript 无法访问存储在http://example.com
HTML5 存储中的项目. - 在子域之间划分.存储在
http://example.com
HTML5 存储中的项目不能被http://sub.example.com
上运行的 JavaScript 访问(你可以做一些 技巧可以解决这个问题.
- divided between http and https. An item stored in
http://example.com
HTML5 storage cannot be accessed by JavaScript running onhttps://example.com
. - divided between subdomains. An item stored in
http://example.com
HTML5 storage cannot be accessed by JavaScript running onhttp://sub.example.com
(you can do some tricks to get around this, however).
饼干更松散:
- 域为
example.com
的 cookie 将同时访问http://example.com
和https://example.com
> 除非它具有secure
属性,在这种情况下它只会被发送到https
. - 未使用明确域发送的 cookie 只会被发送回发送它的确切域.如果域明确定义为
example.com
,那么它将被发送到example.com
和sub.example.com
.(这是cookie规范"中最令人困惑的部分,不幸的是,参见这篇文章). - 如果 cookie 在具有匹配域的页面上运行(并尊重
secure
cookie 标志),则 JavaScript 可以读取该 cookie 除非该 cookie 具有httpOnly
属性,在这种情况下 JavaScript 将无法读取它.
- A cookie with a domain
example.com
will go to bothhttp://example.com
andhttps://example.com
unless it has the attributesecure
, in which case it will only be sent tohttps
. - A cookie not sent with an explicit domain will only be sent back to the exact domain that sent it. If the domain is explicitly defined to be
example.com
, then it will be sent to bothexample.com
andsub.example.com
. (This is the most confusing part of the cookie "spec", unfortunately, see this article). - A cookie can be read by JavaScript if it is running on a page with a matching domain (and respecting the
secure
cookie flag) unless the cookie has thehttpOnly
attribute, in which case JavaScript will not be able to read it.
其次,由于 cookie 标有域,当向服务器发出请求时,浏览器将发送具有匹配域的 all-and-only cookie,无论发起请求的页面的域如何请求.
Second, since cookies are marked with a domain, when a request is made to a server, the browser will send all-and-only cookies with a matching domain, regardless of the domain of the page that originated the request.
最后一部分是 CSRF 攻击是如何完成的(同源策略只提供这么多帮助).CSRF 上的 OWASP 页面 是了解这些类型的好资源攻击有效.
The last part is how a CSRF attack is accomplished (the same-origin policy only helps so much). The OWASP page on CSRF is a good resource for learning how these kinds of attacks work.
将身份验证令牌存储在本地存储中并手动将其添加到每个请求以防止 CSRF 的原因是关键字:手动.由于浏览器不会自动发送该身份验证令牌,如果我访问 evil.com
并设法发送 POST http://example.com/delete-my-account
>,它将无法发送我的身份验证令牌,因此该请求将被忽略.
The reason storing an authentication token in local storage and manually adding it to each request protects against CSRF is that key word: manual. Since the browser is not automatically sending that auth token, if I visit evil.com
and it manages to send a POST http://example.com/delete-my-account
, it will not be able to send my authn token, so the request is ignored.
考虑到上述情况,是否使用 cookie 或 HTML5 Storage 成为一系列权衡:
With the above in mind, whether to use a cookie or HTML5 Storage becomes a series of tradeoffs:
在 HTML5 Storage 中存储身份验证令牌意味着:
Storing the authen token in HTML5 Storage means:
(-)
在 XSS 攻击中被盗的风险.(+)
提供 CSRF 保护.(-)
必须手动修改发送到服务器的每个请求,将您限制为 SPA(例如 AngularJs)Web 应用程序.
(-)
Risk of it getting stolen in an XSS attack.(+)
Provides CSRF protection.(-)
Must manually modify each request going to the server, limiting you to SPA (eg AngularJs) web applications.
另一方面,如果您将身份验证令牌存储在标记为 httpOnly
and secure
的 cookie 中,则:
On the other hand, if you store the authn token in a cookie marked httpOnly
and secure
, then:
(+)
XSS 无法窃取 authn 令牌.(-)
你必须自己提供 CSRF 保护.在某些框架中实施 CSRF 保护比其他框架更容易.
(+)
The authn token cannot be stolen by XSS.(-)
You will have to provide CSRF protection yourself. Implementing CSRF protection is easier in some frameworks than others.
哪个选项更好取决于您的需求.
Which option is better depends on your needs.
- 您的身份验证令牌是否保护与金钱有关的任何事物?您可能需要 cookie
httpOnly
secure
选项. - 实施 CSRF 保护所需的努力水平是否不值得它保护的资产?那么 HTML5 存储可能是正确的地方.
这篇关于使用 JSON Web 令牌的 CSRF 保护的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!