浏览器什么时候发送 Origin header?浏览器什么时候将原点设置为空?

When do browsers send the Origin header? When do browsers set the origin to null?

this Bugzilla thread (and also), Firefox does not always send an Origin header in POST requests. The RFC states that it should not be sent in certain undefined "privacy-sensitive" contexts. Mozilla defines those contexts here可以看出。

我想知道这些是否是 Firefox 不会发送 Origin 的唯一情况 header。据我所知,它也不会在 cross-origin POST 请求中发送(尽管 Chrome 和 Internet Explorer 会),但我无法在文档中确认这一点。是否列举了我遗漏的地方?

就相关规范的实际要求而言,答案分为几个部分:

  • 当浏览器必须在内部将原点设置为将被序列化为 null
  • 的值时
  • 当浏览器必须发送 Origin 时 header

详情如下:

当浏览器必须将 origin 设置为将被序列化为 null

的值时

HTML 规范使用术语 opaque origin 并将其定义为“内部值”:

with no serialization it can be recreated from (it is serialized as "null" per ASCII serialization of an origin), for which the only meaningful operation is testing for equality

换句话说,HTML 规范到处都说 不透明来源 ,您可以将其翻译成 null.

HTML 规范要求浏览器在这些情况下设置不透明来源或唯一来源:

  1. Cross-origin images (including cross-origin img elements)
  2. Cross-origin media data (including cross-origin video and audio elements)
  3. Any document generated from a data: URL
  4. Any iframe with a sandbox attribute that doesn’t contain the value allow-same-origin
  5. Any document programmatically created using createDocument(), etc.
  6. Any document that does not have a creator browsing context
  7. Responses that are network errors
  8. The Should navigation response to navigation request of type from source in target be blocked by Content Security Policy? algorithm returns Blocked when executed on a navigate response

在一种情况下,Fetch 规范要求浏览器将来源设置为“全球唯一标识符”(这基本上与“不透明来源”的意思相同,基本上意味着 null…):

  1. Redirects across origins

URL 规范要求浏览器在以下情况下设置不透明来源:

  1. For blob: URLs
  2. For file: URLs
  3. For any other URLs whose scheme is not one of http, https, ftp, ws, wss, or gopher.

但请注意,仅仅因为浏览器在内部设置了一个不透明的来源——本质上是 null——并不一定意味着浏览器会发送 Origin header。因此,请参阅此答案的下一部分,了解有关浏览器何时必须发送 Origin header.

的详细信息

当浏览器必须发送 Origin 时 header

浏览器发送 Origin header 用于 cross-origin 由 fetch() 或 XHR 调用发起的请求,或通过 ajax 方法发起的 JavaScript 库(axios、jQuery 等)——但不适用于正常的页面导航(即,当您直接在浏览器中打开网页时),并且(通常)不适用于网络中嵌入的资源页面(例如,不适用于 CSS 样式表、脚本或图像)。

但该描述是一种简化。当浏览器发送 Origin header 时,除了 cross-origin XHR/fetch/ajax 调用之外,还有浏览器发送 Origin header 嵌入资源的情况.所以下面是更长的答案。


根据规范要求:规范要求 Origin header 仅针对 Fetch 规范定义为 CORS request 的任何请求发送:

A CORS request is an HTTP request that includes an Origin header. It cannot be reliably identified as participating in the CORS protocol as the Origin header is also included for all requests whose method is neither GET nor HEAD.

所以,规范的意思是:Origin header 在所有 cross-origin 请求中发送, 它也总是针对所有 POSTPUTPATCHDELETE 请求发送 — 甚至 same-origin POSTPUTPATCHDELETE 请求(根据 Fetch 中的定义,实际上是“CORS 请求”——尽管它们是 same-origin)。*


浏览器必须发送 Origin header 的其他情况是在发出请求时设置了“CORS 标志”——就 HTTP(S) 请求而言,是 except when the request mode is navigate, websocket, same-origin, or no-cors.

XHR 总是 将模式设置为 cors。但是对于 Fetch API,这些请求模式是您可以使用 fetch(…) 方法的 init-object 参数的 mode 字段设置的模式:

fetch("http://example.com", { mode: 'no-cors' }) // no Origin will be sent

字体请求始终将模式设置为 cors,因此始终将 Origin header.

并且对于具有 a crossorigin attribute 的任何元素(aka “CORS 设置属性”),HTML 规范要求浏览器将请求模式设置为 cors(并发送 Origin header)。

否则,对于嵌入式资源——任何具有 URL 属性的元素都会发起请求(<script src>、样式表、图像、媒体元素)——请求的模式默认为 no-cors;由于这些请求是 GET 请求,这意味着 per-spec,浏览器不会为它们发送 Origin header。

当 HTML 表单元素发起 POST 请求时,那些 POST 的模式也默认为 no-cors — 与嵌入资源有其模式的方式相同默认为 no-cors。但是,与 no-cors 模式 GET 对嵌入式资源的请求不同,浏览器确实会为那些从 no-cors 模式 POST 发起的请求发送 Origin header HTML 表单元素。

原因是,如本回答前面所述,浏览器总是发送 Origin header 总共 POSTPUTPATCH,以及 DELETE 个请求。

此外,为了这里的完整性和明确性:对于导航,浏览器不发送 Origin header。也就是说,如果用户直接导航到资源——通过将 URL 粘贴到浏览器地址栏,或者通过跟随来自另一个网络文档的 link——那么浏览器不会发送 Origin header.


要求浏览器对所有CORS请求发送Originheader的algorithm in the Fetch spec是这样的:

追加请求Originheader,给定一个请求请求,运行这些步骤:

1.设 serializedOrigin 为 byte-serializing 请求来源 request.
的结果 2。如果request的响应污染是“cors”或者request的模式是“websocket”,那么
Origin/serializedOrigin 附加到 request 的 header 列表。
3。否则,如果request的方法既不是GET也不是HEAD
然后:[在那种情况下也发送 Origin header]

第 2 步需要在所有 cross-origin 请求中发送 Origin header — 因为所有 cross-origin 请求都有其响应污染设置为“cors”。

但是第 3 步要求 Origin header 也被发送给 same-origin POSTPUTPATCHDELETE 请求(根据 Fetch 中的定义,它们实际上是“CORS 请求”——尽管它们是 same-origin)。

由于 change that was made to the spec on 2016-12-09,上面描述了 Fetch 规范当前如何定义要求。在那之前,要求是不同的:

• 之前没有为 same-origin POST
发送 Origin • 之前没有从 <form>(没有 CORS)

为 cross-origin POST 发送 Origin

因此问题描述的 Firefox 行为是规范以前 所要求的,而不是当前 所要求的。

对我来说,这是在本地主机上以超标准形式 POST 发生在亲戚 URL 上的,并且似乎是由

触发的
<meta name="referrer" content="no-referrer">

<head>.

改成

<meta name="referrer" content="same-origin">

似乎让 Firefox 更快乐。