如您从此Bugzilla线程(以及这个)所看到的,Firefox在POST请求中并不总是发送Origin头信息。RFC规定在某些未定义的“隐私敏感”情况下,不应发送。Mozilla在此处定义了这些情况。
我想知道是否只有在这些情况下Firefox才不会发送Origin头信息。据我所知,它还不会在跨域POST请求中发送它(尽管Chrome和Internet Explorer会),但我无法在文档中确认。是否有我遗漏的列出这些情况的地方?
如您从此Bugzilla线程(以及这个)所看到的,Firefox在POST请求中并不总是发送Origin头信息。RFC规定在某些未定义的“隐私敏感”情况下,不应发送。Mozilla在此处定义了这些情况。
我想知道是否只有在这些情况下Firefox才不会发送Origin头信息。据我所知,它还不会在跨域POST请求中发送它(尽管Chrome和Internet Explorer会),但我无法在文档中确认。是否有我遗漏的列出这些情况的地方?
就实际要求的相关规范而言,答案有几个部分:
null
的值时以下是详细信息:
null
的值时HTML规范使用术语opaque origin并将其定义为“内部值”:
没有序列化时,它可以从中重新创建(按照原点的ASCII序列化,它被序列化为"null"),唯一有意义的操作是测试相等性
换句话说,无论HTML规范在哪里提到opaque origin,您都可以将其翻译为null
。
HTML规范要求浏览器在以下情况下设置不透明原点或唯一原点:
img
元素)video
和audio
元素)data:
URL生成的任何文档sandbox
属性且不包含值allow-same-origin
的iframe
createDocument()
等程序创建的任何文档根据Fetch规范,浏览器需要在以下情况下将origin设置为“全局唯一标识符”(基本上与“不透明起源”(即基本上意味着 null
…)相同):
URL规范要求浏览器在以下情况下设置不透明起源:
但请注意,仅因为浏览器在内部设置了一个不透明的来源(基本上是null
),这并不一定意味着浏览器将发送一个Origin
头。因此,请参阅本答案的下一部分,以了解浏览器必须发送Origin
头的详细信息。
浏览器在WebSocket请求和由fetch()
或XHR调用发起的跨源请求中发送Origin
头,或者由JavaScript库(axios、jQuery等)的ajax方法发起的跨源请求中发送Origin
头,但不会在正常页面导航(即在浏览器中直接打开网页时)以及嵌入在网页中的资源(例如CSS样式表、脚本或图像)中发送(通常情况下)。
但这只是一个简化。除了WebSocket请求和跨源XHR/fetch/ajax调用之外,还有其他情况下浏览器会发送Origin
头,并且在嵌入资源时也会发送Origin
头。因此,下面是更详细的答案。
Origin
标头:
因此,规范的意思是:在所有跨域请求中都会发送CORS 请求 是包括
Origin
标头的 HTTP 请求。由于Origin
标头“也包括所有方法不是GET
或HEAD
的请求”,因此无法可靠地确定其是否参与 CORS 协议。
Origin
标头,但对于所有 POST
、PUT
、PATCH
和 DELETE
请求,甚至对于同源的 POST
、PUT
、PATCH
和 DELETE
请求(根据 Fetch 的定义,它们实际上是“CORS 请求”——尽管它们是同源的),也始终会发送该标头。*
浏览器必须发送Origin
头的另一种情况是在设置了“CORS标志”的任何请求中,这在HTTP(S)请求方面是除非请求模式为navigate
、websocket
、same-origin
或no-cors
。
XHR 总是将模式设置为cors
。但使用Fetch API时,这些请求模式是您可以使用init-object参数的mode
字段设置到fetch(…)
方法中的那些模式:
fetch("http://example.com", { mode: 'no-cors' }) // no Origin will be sent
字体请求始终将模式设置为cors
,因此始终具有Origin
标头。
对于任何带有{{link1:crossorigin
属性}}(也称为“CORS设置属性”)的元素,HTML规范要求浏览器将请求模式设置为cors
(并发送Origin
标头)。
否则,对于嵌入资源 - 任何具有启动请求的URL属性的元素(<script src>
、样式表、图像、媒体元素) - 请求的模式默认为no-cors
;由于这些请求是GET
请求,因此根据规范,浏览器不会为它们发送Origin
标头。
当HTML表单元素发起POST
请求时,这些POST
的模式也默认为no-cors
,就像嵌入资源的模式默认为no-cors
一样。然而,与嵌入资源的GET
请求不同的是,浏览器会发送Origin
头信息给那些从HTML表单元素发起的no-cors
模式的POST
。
原因是,正如本答案中早先提到的,浏览器总是在所有POST
、PUT
、PATCH
和DELETE
请求中发送Origin
头信息。
此外,为了完整和清晰:对于导航,浏览器不发送Origin
头信息。也就是说,如果用户直接导航到一个资源——通过将URL粘贴到地址栏中,或者通过从另一个Web文档中跟随链接——那么浏览器不会发送Origin
头信息。
*Fetch规范中的算法要求浏览器对所有CORS请求发送Origin
头,该算法如下:
为请求request附加一个请求Origin
头,请执行以下步骤:
1. 让serializedOrigin成为使用request进行字节序列化的请求来源的结果。
2. 如果request的响应污染是"cors
"或request的模式是"websocket
",那么
将Origin
/serializedOrigin附加到request的头部列表中。
3. 否则,如果request的方法既不是GET
也不是HEAD
,
那么:[在这种情况下也发送Origin
头]
第二步要求在所有跨域请求中发送Origin
头,因为所有跨域请求的响应污染设置为"cors
"。
但是第三步还要求在同源的POST
、PUT
、PATCH
和DELETE
请求中也发送Origin
头(根据Fetch的定义,它们实际上是“CORS请求”——尽管它们是同源的)。
以上描述了Fetch规范目前如何定义要求,这是由于2016年12月9日对规范进行的更改。在那之前,要求是不同的:
• 先前同源POST未发送Origin
• 先前未在没有CORS的情况下从<form>
进行跨域POST发送Origin
因此,Firefox的行为是描述问题的规范先前所要求的,而不是当前所要求的。
Origin
标头值为null
时完整概述的唯一权威。甚至MDN文档都引用了你的回答。我一直在查看你提供的各种(过时的)链接,但除了问题中提到的那些来源外,我没有找到任何支持你论点的来源。你是如何发现例如Content-Security-Policy的情况的呢? - Advena<meta name="referrer" content="no-referrer">
<head>
中。
将其更改为:<meta name="referrer" content="same-origin">
似乎让Firefox更加愉快。
Referrer-Policy no-referrer
头导致Origin未设置(随后由于CORS被拒绝请求)。 - Dario Seidlreferer
,但当设置为 no-referrer
时,它还会导致浏览器发送 Origin:null
。 - andrewdotn我想在@sideshowbarker的优秀回答中添加一些信息,这已成为该主题最全面的来源,甚至被MDN链接。为了补充这个答案,我查阅了各种规范,并确定了自回答发布以来发生的一些变化。我还组织了信息,使其更易于阅读。此外,我使用了2023年初的WebArchive引用,而不是直接链接,因为规范可能会在未来发生变化。
需要注意的是,@sideshowbarker和我的回答都应作为指南使用,因为浏览器维护者的实现、规则集和风格取决于他们的判断。
将它们用作指南,如果您不确定,请务必进行测试。
正如@sideshowbarker所提到的,各种规范将空的Origin
头定义为:
有了这个,我们可以通过规范来过滤出何时Origin
头是null
的:
GET
或HEAD
请求不允许跨源资源共享(CORS)或使用Websockets。对于所有其他使用same-origin
,navigate
或no-cors
的请求模式,Origin标头被省略。一些Web API允许您指定mode
,例如fetch
,而其他API具有默认值,例如请求外部资源的<img>
:1, 2
<link>
,<script>
,<img>
,<audio>
,<video>
,<object>
,<embed>
和<iframe>
。这些HTTP GET
请求默认使用no-cors
模式,除非在HTML元素上设置了crossorigin
属性。请注意,<canvas>
,<math>
和<svg>
不包括在内,因为它们无法从外部资源请求数据(例如使用src
属性)。1, 2, 3GET
或HEAD
fetch()
请求,其中mode
选项的值为"navigate"
,"same-origin"
或"no-cors"
。默认情况下,fetch()
使用cors
模式。1, 2XMLHttpRequest
,与fetch
不同,不允许设置mode
并默认为cors
,这意味着所有XMLHttpRequest
都带有Origin标头。)4Referrer-Policy
设置为no-referrer
,适用于不使用GET
或HEAD
方法且不使用cors
或websocket
的任何请求。5<a>
,<iframe>
,window.location
)或提交表单的位置(通过<form>
)。fetch
响应不被视为导航响应。7data:
方案创建的任何嵌入式内联文件8file:
方案可能省略Origin标头(浏览器相关)91 在fetch规范中,除了GET
或HEAD
请求外,所有请求都会包含源(Origin)信息。
2 在fetch规范中,使用cors
或websocket
模式时会带有源(Origin)头,但其他模式则不带。
3 Request()
构造函数的默认模式用于fetch
和嵌入式HTML元素。
4 根据XHR规范,默认的XMLHttpRequest
模式设置为cors
。
5 fetch规范在第3.1小节中提到了这一点。
6 HTML规范规定,网络错误不应返回任何导航参数,包括来源(origins)。请参见21号(而非19.21号)小节。
7 HTML规范规定,“Blocked” CSP响应会导致网络失败。请参见6.5号小节。其中CSP规范将其定义为网络错误,参见引用5。
8 HTML规范规定,“data:”方案返回一个不透明的源(opaque origin)。
9 URL规范规定,读者应决定如何处理“file:”方案,但建议使用不透明的源(opaque origin)。
10 FileAPI规范列出了一些特定情况,这些情况下会使用不透明的源(opaque origin)。
11 URL规范列出了这些URL方案及其回退到“不透明的源(opaque origin)”的情况。
12 HTML规范指定在此iframe上下文中返回一个“不透明的源(opaque origin)”。请参见第5号小节。
13 HTML规范规定,没有浏览上下文的Document
具有“不透明的源(opaque origin)”。此外,HTML规范还规定使用createDocument()
创建的Document
也没有浏览上下文。