Когда Firefox устанавливает нулевой заголовок Origin в запросах POST?
Как вы можете видеть из этого потока Bugzilla (а также), Firefox не всегда отправляет заголовок Origin в запросах POST. RFC заявляет, что его не следует отправлять в определенных неопределенных контекстах, "чувствительных к конфиденциальности". Mozilla определяет эти контексты здесь.
Я хотел бы знать, являются ли это единственными ситуациями, когда Firefox не отправляет заголовок Origin. Насколько я могу судить, он также не будет отправлять запросы POST (хотя Chrome и IE будут это делать), но я не могу подтвердить это в документации. Это где-то перечислено, что я скучаю?
Благодарю.
3 ответа
Насколько требуют спецификации, вопрос выше должен быть разделен на пару ответов:
- Когда браузеры должны отправить заголовок Origin
- Когда браузеры должны внутренне установить источник в значение, которое будет сериализовано как
null
Я сомневаюсь, что то, что требуется Firefox для этого (где оно отличается от спецификации), перечислено. Но что касается перечисления спецификационных требований, здесь они, в деталях, состоят из двух частей:
Когда браузеры должны отправить заголовок Origin
Ответ на вопрос Когда браузеры должны отправлять заголовок Origin? это Origin
заголовок отправляется только для любого запроса, который спецификация Fetch определяет как запрос CORS:
CORS-запрос - это HTTP-запрос, который включает
Origin
заголовок. Он не может быть надежно идентифицирован как участвующий в протоколе CORS, посколькуOrigin
заголовок также включен для всех запросов, чей метод неGET
ниHEAD
,
Фактическое утверждение в спецификации Fetch, которое требует от браузеров отправлять Origin
заголовок для всех запросов, чей метод не GET
ни HEAD
это:
Если установлен флаг CORS или метод httpRequest не является
GET
ниHEAD
, а затем добавитьOrigin
Происхождение / httpRequest, сериализованное и закодированное в UTF-8, в список заголовков httpRequest.
Так что для отправки требуется браузер Origin
для всех POST
запросы, в том числе одного происхождения POST
s (которые по определению в Fetch на самом деле являются "запросами CORS" - даже если они одного происхождения).
Примечание. Выше описано, как спецификация Fetch в настоящее время определяет требования, в связи с изменением спецификации в 2016-12-09. До тех пор требования были другими:
- ранее нет
Origin
был отправлен для одного и того же происхождения POST - ранее нет
Origin
был отправлен на отправку перекрестного происхождения из<form>
(без CORS)
Поэтому я думаю, что поведение Firefox, описанное в этом вопросе, соответствует тому, что ранее требовалось для спецификации, а не тому, что требует спецификация в настоящее время.
Другие случаи, когда браузеры должны отправлять Origin
заголовок - это любые случаи, когда запрос сделан с установленным "флагом CORS", который, насколько HTTP(S) запросы, кроме случаев, когда режим запроса navigate
, websocket
, same-origin
, или же no-cors
,
XHR всегда устанавливает режим на cors
, Но с Fetch API эти режимы запросов можно установить с помощью mode
поле аргумента объекта init для fetch(…)
метод:
fetch("http://example.com", { mode: 'no-cors' }) // no Origin will be sent
Наряду с этим, для любого элемента с crossorigin
атрибут (он же "атрибут установки CORS), спецификация HTML требует, чтобы браузеры установили режим запроса на cors
(и отправить Origin
заголовок).
В противном случае для любых элементов, инициирующих запросы (скрипты, таблицы стилей, изображения, медиа-элементы), режим для запросов по умолчанию равен no-cors
, что означает нет Origin
Заголовок отправляется для них.
Так что выше приведены подробности об условиях, при которых браузеры отправляют Origin
заголовок.
Следующая часть ответа о том, когда начальное значение будет установлено на null
,
Когда браузеры должны установить origin на значение, которое будет сериализовано как null
Отдельно от требований, когда браузеры должны отправлять Origin
заголовок - это требования, когда браузеры должны установить источник в null
, которые определены в следующих спецификациях:
Спецификация HTML использует термин непрозрачное происхождение и говорит следующее:
Внутреннее значение, без сериализации, из которого оно может быть воссоздано (оно сериализуется как "ноль" для ASCII-сериализации источника), для которого единственной значимой операцией является проверка на равенство.
Другими словами, везде, где в спецификации HTML указано непрозрачное происхождение, вы можете перевести это на null
,
Спецификация HTML требует, чтобы браузеры устанавливали непрозрачный источник или уникальный источник в следующих случаях:
- Изображения перекрестного происхождения (включая перекрестное происхождение
img
элементы) - Медиа-данные перекрестного происхождения (включая перекрестное происхождение
video
а такжеaudio
элементы) - Любой документ, сгенерированный из
data:
URL - любой
iframe
сsandbox
атрибут, который не содержит значениеallow-same-origin
- Любой документ, программно созданный с использованием
createDocument()
, так далее. - Любой документ, который не имеет контекста просмотра создателя
- Ответы, которые являются ошибками сети
- Должна ли политика безопасности контента блокировать ответ навигации на запрос навигации типа от источника в цели? Алгоритм возвращает Заблокированный при выполнении в ответе навигации
Спецификация Fetch требует, чтобы браузеры устанавливали в качестве источника "глобально уникальный идентификатор" (что в основном означает то же самое, что и "непрозрачное происхождение", что в основном означает null
…) В одном случае:
Спецификация URL требует, чтобы браузеры устанавливали непрозрачное происхождение в следующих случаях:
- За
blob:
URL - адрес - За
file:
URL - адрес - Для любых других URL, чья схема не является одной из
http
,https
,ftp
,ws
,wss
, или жеgopher
,
Но важно понимать, что только потому, что браузер внутренне установил непрозрачное происхождение - по сути, null
- это не обязательно означает, что браузер отправит Origin
заголовок. Так что смотрите первую часть этого ответа, чтобы узнать, когда браузеры должны отправлять Origin
заголовок.
Для меня это происходило в суперстандартной форме POST с относительным URL-адресом на локальном хосте и, похоже, было вызвано тем, что
<meta name="referrer" content="no-referrer">
в
<head>
.
Изменение его на
<meta name="referrer" content="same-origin">
казалось, сделал Firefox счастливее.
Я хотел добавить некоторую информацию к великолепному ответу @sideshowbarker , который стал наиболее полным источником по этой теме и даже связан с MDN . Чтобы дополнить этот ответ, я рассмотрел различные спецификации и выявил некоторые изменения, произошедшие с момента первой публикации ответа. Я также систематизировал информацию, чтобы ее было легче читать. Кроме того, я использовал ссылки на WebArchive начала 2023 года вместо прямых ссылок, поскольку в будущем спецификации могут измениться.
Важно отметить, что и , и мой ответ следует использовать в качестве рекомендаций, поскольку реализации, наборы правил и варианты остаются на усмотрение разработчиков браузера.
Используйте их в качестве руководства, а если вы не уверены, обязательно проведите тесты.
Как упомянул user441757 , различные спецификации определяют нулевое значение. заголовок как:
- непрозрачное происхождение
- нулевое происхождение
Благодаря этому мы можем фильтровать спецификации, чтобы выяснить, когдаOrigin
заголовокnull
:
- или запросы, которые не допускают совместное использование ресурсов между источниками (CORS) или используют веб-сокеты . Для всех других режимов запроса , использующих
same-origin
,navigate
или заголовок Origin опускается. Некоторые веб-API позволяют указать , например , а другие имеют значения по умолчанию, например запрос внешнего ресурса: 1, 2.- Любой встроенный HTML-элемент, который запрашивает свое содержимое через URL-адрес. Эти элементы включают в себя
<link>
,<script>
,<img>
,<audio>
,<video>
,<object>
,<embed>
, и . Эти HTTP-запросы используютno-cors
режим по умолчанию, если толькоcrossorigin
Атрибут установлен в элементе HTML. Обратите внимание, что<canvas>
,<math>
, и<svg>
не включены, так как не могут запрашивать данные из внешних ресурсов (например, с помощьюsrc
атрибут). 1, 2, 3 - Любой или запрос, где опция имеет значение
"navigate"
,"same-origin"
, или"no-cors"
. По умолчанию,fetch()
использует режим. 1, 2 - (Примечание: , в отличие от не позволяет устанавливать a и по умолчанию равно , что означает, что все отправляются с заголовком Origin. )4
- Любой встроенный HTML-элемент, который запрашивает свое содержимое через URL-адрес. Эти элементы включают в себя
-
Referrer-Policy
установлен вno-referrer
для любых запросов, которые не используют метод или и не используют или . 5 - Ответы, которые являются сетевыми ошибками . Статус HTTP-ответа 404 или 500 не является сетевой ошибкой, поскольку запрос успешно достиг сервера. Скорее неверный протокол, заголовок или место, где сервер не может отправить ответ. 6
- Content-Security-Policy (CSP) заблокировал ответы навигации. Термин «навигационные ответы» относится к местам, к которым пользователь может перейти (через
<a>
, ,window.location
) или отправьте форму (через<form>
). ответы не считаются навигационными ответами. 7 - Схемы URL :
- Любой встроенный встроенный файл, созданный по схеме 8.
- В схеме может отсутствовать заголовок Origin (зависит от браузера) 9
- В некоторых случаях для
blob:
схема 10 - Любой другой URL-адрес, схема которого не является одной из
http
,https
,ftp
,ws
,wss
илиgopher
11
- Некоторые контексты просмотра не имеют Origin . Контекст просмотра — это среда, в которой отображается веб-страница или приложение, которая может быть вкладкой , окном или даже частями страницы, например фреймом или iframe . Создатель (в предыдущих спецификациях HTML он назывался «контекстом просмотра создателя» ) — это контекст просмотра, который отвечал за создание другого контекста просмотра. Существует два типа создателей: открывающий контекст просмотра (например, щелчок по ссылке на другую страницу, страница, в которую вставлена ссылка, является открывающим) и родительский контекст просмотра (например, страница, встраивающая iframe, является родительским контекстом просмотра). Спецификация HTML рассматривает следующие случаи без заголовка Origin:
- Любой
<iframe>
сsandbox
атрибут, который не содержит значенияallow-same-origin
12 - Любой документ, созданный программным путем с использованием контекста просмотра создателя или не имеющий его. 13, 14
- Любой
Использованная литература:
1 В спецификации выборки указано, что Origin включен для всех запросов, кроме
GET
или
HEAD
.
2
3 Режим по умолчанию
Request()
конструктор, используемый для
fetch
и встроенные элементы HTML
4. В спецификации XHR указано, что режим по умолчанию
XMLHttpRequest
установлено на
cors
5 В спецификации выборки указано, что
В спецификации выборки это упоминается в пункте № 3.1.mode
с или
websocket
отправляются с заголовком Origin, исключая все остальные режимы.
6 Спецификация HTML гласит, что сетевая ошибка не должна возвращать никакие параметры навигации, включая происхождение. См. пункт № 21 (не № 19.21).
7 В спецификации HTML указано, что «заблокированный» ответ CSP приводит к сбою сети. См. пункт № 6.5 , который в спецификациях CSP определяется как сетевая ошибка , устраняемая в ссылке 5.
8 В спецификации HTML говорится, что
data:
Схема возвращает непрозрачный источник.
9
10 В спецификации URL указано, что читатель должен решить, как обрабатывать
непрозрачного источника использованияfile:
11 В спецификации FileAPI перечислены некоторые конкретные случаи В. »спецификации URL перечислены эти схемы URL и резервные варианты
. 12 «непрозрачного происхождения В спецификации HTML указано, что для этот контекст случая iframe. См. пункт № 5.
13 Спецификация HTML гласит, что контекст без просмотра имеет «непрозрачное происхождение» . Более того, спецификация HTML гласит, что Document
's' создано с
createDocument()
не иметь контекста просмотра