为什么XMLHttpRequest包含一个Origin头部?

6
我希望更好地理解这个问题。我目前所使用的思维模型如下:
1. JS 托管在 foo.com 上,希望访问托管在 bar.com 上的资源。这不是浏览器想要向其用户公开的事情,除非可以证明 bar.com 欢迎此请求。
2. 因此,foo.com JS 实际上将请求分成两半。首先,我们通过 XMLHttpRequest 对象发送一个不带数据的请求(GET、POST 等)。bar.com 服务器返回它通常对任何请求响应的内容,其中可能包括 Access-Control-Allow-Origin 标头。(编辑:这是一个误解——请参见下面 apsillers 的优秀评论)
3. 如果浏览器确实收到了这样的标头,则会扫描其中的 Origin(在本例中为 foo.com)。如果存在,则继续发送它被要求发送的实际请求。否则,它会拒绝。(编辑:这也不完全正确)
如果这个模型是正确的,那么我不明白为什么浏览器会在这个初步请求中发送 Origin 标头。难道检查匹配不是在客户端进行吗?发送这个标头有什么作用?

1
实际上,没有数据的预检请求仅在“非简单”HTTP动词(例如PUT、DELETE等)除了GET和POST时发生,并且预检请求使用OPTIONS动词。 - apsillers
1
@apsillers -- 使用其他动词自定义标题。我不知道为什么;我猜这补丁修复了一些安全漏洞。 - Michael Lorton
2
正确的。在CORS术语中,GET和POST被称为“简单”的HTTP动词,并且允许它们到达跨源服务器(但浏览器可能会在HTTP请求完成后决定JS无法看到结果)。Origin头可能在这里很有用,因为任何来源都可以成功地向任何其他来源发送GET/POST请求,但如果浏览器阻止它,则响应可能对JavaScript不可见。(除了GET和POST之外的请求在成功的OPTIONS预检之前不允许到达服务器,这一点您已经理解了。) - apsillers
总之,一个支持CORS的浏览器总是发出GET/POST请求,而不考虑来源,但它可能会根据同源策略拒绝JavaScript访问响应数据。您也可以参考我之前的这个回答 - apsillers
@apsillers - 谢谢!在你和epascarello的帮助下,我的理解水平确实有了很大提高。我还有一点点不太清楚的地方——为什么Chrome会在GET请求中发送Origin头?这对我来说似乎有点低效;我现在确定没有服务器使用这些信息(因为它是GET而不是OPTIONS),而且Chrome在响应到达时可能已经可以访问Origin了。但也许Chrome没有以任何方便的方式访问这些信息,这是行政上的便利问题。 - Greg Pallis
显示剩余3条评论
1个回答

3
这是CORS如何工作的方式。基本上,这是一种握手方式,表示欢迎与我交流。除非联系第三方,否则您无法确定是否可能。
以下是MDN文章中Preflighted_requests部分的部分内容:
与简单请求不同(上文已讨论),"预检"请求首先向其他域上的资源发送HTTP OPTIONS请求头,以确定实际请求是否安全可发送。由于跨站点请求可能涉及用户数据,因此会像这样进行预检。特别是,如果请求满足以下条件,则会进行预检: - 使用除GET或POST之外的方法。 - 如果使用POST发送请求数据,并且Content-Type不是application/x-www-form-urlencoded、multipart/form-data或text/plain等类型,例如,如果POST请求使用application/xml或text/xml向服务器发送XML有效载荷,则该请求将进行预检。 - 在请求中设置自定义标头(例如,请求使用诸如X-PINGOTHER之类的标头)。

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