为什么浏览器 API 会限制跨域请求? [英] Why do browser APIs restrict cross-domain requests?
问题描述
XMLHttpRequest
需要 CORS 才能跨域工作.对于网络字体、WebGL 纹理和其他一些东西也是如此.一般来说,所有新的 API 似乎都有这个限制.
XMLHttpRequest
s require CORS to work cross-domain. Similarly for web fonts, WebGL textures, and a few other things. In general all new APIs seem to have this restriction.
为什么?
绕过它非常容易:只需要一个简单的服务器端代理.换句话说,服务器端代码不被禁止做跨域请求;为什么是客户端代码?这如何为任何人提供任何安全保障?
It's so easy to circumvent: all it takes is a simple server-side proxy. In other words, server-side code isn't prohibited from doing cross-domain requests; why is client-side code? How does this give any security, to anyone?
而且它是如此不一致:我不能 XMLHttpRequest
,但我可以 或
或
或
.限制 XHR 等甚至可以完成什么?
And it's so inconsistent: I can't XMLHttpRequest
, but I can <script src>
or <link rel>
or <img src>
or <iframe>
. What does restricting XHR etc. even accomplish?
推荐答案
如果我访问恶意网站,我想确定:
If I visit a malicious website, I want to be sure that :
- 它无法从我使用的其他网站读取我的个人数据.想想攻击者.com 阅读 gmail.com
- 它不能代表我在我使用的其他网站上执行操作.想想攻击者.com 从我在 bank.com 上的帐户转移资金
- It cannot read my personal data from other websites I use. Think attacker.com reading gmail.com
- It cannot perform actions on my behalf on other websites that I use. Think attacker.com transferring funds from my account on bank.com
同源策略解决了第一个问题.第二个问题称为跨站请求伪造,目前跨域限制无法解决.
Same Origin Policy solves the first problem. The second problem is called cross site request forgery, and cannot be solved with the cross-domain restrictions currently in place.
同源策略大体上符合以下规则——
The same origin policy is in general consistent with the following rules -
- 规则 1:不允许您阅读来自不同域的任何内容
- 规则 2:允许您将任何内容写入不同的域,但规则 1 不允许您读取响应.
- 规则三:可以自由地进行跨域的 GET 请求和 POST 请求,但不能控制 HTTP 标头
让我们看看您列出的各种内容如何符合上述规则:
Lets see how the various things you have listed line up to the above rules :
<img>
标签可以让你发出一个 HTTP 请求,但是除了简单地显示它之外,没有办法读取图像的内容.例如,如果我这样做<img src="http://bank.com/get/latest/funds"/>
,请求将通过(规则 2).但是攻击者无法看到我的余额(规则 1).
<img>
tags let you make a HTTP request, but there is no way to read the contents of the image other than simply displaying it. For example, if I do this<img src="http://bank.com/get/latest/funds"/>
, the request will go through (rule 2). But there is no way for the attacker to see my balance (rule 1).
<script>
标签的工作方式与 <img>
非常相似.如果您执行 <script src="http://bank.com/get/latest/funds">
之类的操作,请求将通过.浏览器也会尝试将响应解析为 JavaScript,但会失败.
<script>
tags work mostly like <img>
. If you do something like <script src="http://bank.com/get/latest/funds">
, the request will go through. The browser will also try to parse the response as JavaScript, and will fail.
<script>
标签被称为 JSONP 的一种众所周知的滥用行为,在这种情况下,您与跨域服务器勾结,以便您可以读取"跨域.但是如果没有跨域服务器的明确参与,您将无法通过 <script>
标签
There is a well known abuse of <script>
tags called JSONP, where you collude with the cross-domain server so that you can 'read' cross-domain. But without the explicit involvement of the cross-domain server, you cannot read the response via the <script>
tag
<link>
与 <script>
标签的工作方式很相似,只是响应被评估为 CSS.通常,您无法读取响应 - 除非响应碰巧是格式正确的 CSS.
<link>
for stylesheets work mostly like <script>
tags, except the response is evaluated as CSS. In general, you cannot read the response - unless the response somehow happens to be well-formed CSS.
<iframe>
本质上是一个新的浏览器窗口.您无法读取跨域 iframe 的 HTML.顺便说一句,您可以更改跨域 iframe 的 URL,但您无法读取该 URL.注意它是如何遵循我上面提到的两条规则的.
<iframe>
is essentially a new browser window. You cannot read the HTML of a cross-domain iframe. Incidentally, you can change the URL of a cross-domain iframe, but you cannot read the URL. Notice how it follows the two rules I mentioned above.
XMLHttpRequest
是发出 HTTP 请求的最通用方法.这完全由开发人员控制;浏览器不会对响应做任何事情.例如,在 <img>
、<script>
或 <link>
的情况下,浏览器采用特定格式并通常会适当地验证它.但在 XHR 中,没有规定的响应格式.因此,除非跨域网站明确允许,否则浏览器会强制执行同源策略并阻止您阅读响应.
XMLHttpRequest
is the most versatile method to make HTTP requests. This is completely in the developers control; the browser does not do anything with the response. For example, in the case of <img>
, <script>
or <link>
, the browser assumes a particular format and in general will validate it appropriately. But in XHR, there is no prescribed response format. So, browsers enforce the same origin policy and prevent you from reading the response unless the cross domain website explicitly allows you.
通过 font-face
的字体是一种反常现象.AFAIK,只有 Firefox 需要选择加入行为;其他浏览器让您可以像使用图像一样使用字体.
Fonts via font-face
are an anomaly. AFAIK, only Firefox requires the opt-in behavior; other browsers let you use fonts just like you would use images.
简而言之,同源策略是一致的.如果您找到一种方法来提出跨域请求并在未经跨域网站明确许可的情况下阅读响应 - 您将成为全世界的头条新闻.
In short, the same origin policy is consistent. If you find a way to make a cross-domain request and read the response without explicit permission from the cross-domain website - you'll make headlines all over the world.
编辑:为什么我不能使用服务器端代理解决所有这些问题?
EDIT : Why can't I just get around all of this with a server-side proxy?
要让 gmail 显示个性化数据,它需要来自您浏览器的 cookie.一些站点使用 HTTP 基本身份验证,其中凭据存储在浏览器中.
For gmail to show personalized data, it needs cookies from your browser. Some sites use HTTP basic authentication, in which the credentials are stored in the browser.
服务器端代理无法访问 cookie 或基本身份验证凭据.因此,即使它可以发出请求,服务器也不会返回用户特定的数据.
A server-side proxy cannot get access to either the cookies or the basic auth credentials. And so, even though it can make a request, the server will not return user specific data.
这篇关于为什么浏览器 API 会限制跨域请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!