Почему XMLHttpRequest включает заголовок Origin?

Я хотел бы понять это немного лучше. Ментальная модель, с которой я сейчас работаю, работает примерно так:

  1. JS, размещенный на foo.com, хочет получить доступ к ресурсу, размещенному на bar.com. Это не то, что браузеры любят показывать своим пользователям, если только нельзя показать, что bar.com приветствует этот запрос.
  2. Таким образом, foo.com JS по существу разбивает запрос на две половины. Сначала мы отправляем запрос без данных надлежащего вида (GET, POST и т. д.) через объект XMLHttpRequest. Сервер bar.com возвращает то, что он обычно отвечает практически на любой запрос, который может включать или не включать заголовок Access-Control-Allow-Origin. (РЕДАКТИРОВАТЬ: это было заблуждение - см. отличный комментарий от апсиллеров ниже)
  3. Если браузер получает такой заголовок, он сканирует его в поисках источника (в данном случае foo.com). Если он присутствует, он продолжает отправлять фактический запрос, который его просили отправить. Если нет, то отказывается. (РЕДАКТИРОВАТЬ: это тоже было не совсем правильно)

Если эта модель верна, я не понимаю, почему браузер отправляет заголовок Origin с этим предварительным запросом. Разве проверка соответствия не происходит на стороне клиента? Что дает отправка этого заголовка?


person Greg Pallis    schedule 19.11.2012    source источник
comment
На самом деле предварительный запрос без данных происходит только с непростыми HTTP-глаголами, отличными от GET и POST (например, PUT, DELETE и т. д.), а предварительный запрос использует глагол OPTIONS.   -  person apsillers    schedule 19.11.2012
comment
@apsillers -- другой глагол или использование пользовательского заголовка. Я не знаю почему; Я предполагаю, что это исправляет некоторую дыру в безопасности.   -  person Malvolio    schedule 19.11.2012
comment
@Malvio Хорошо, спасибо, я забыл о заголовках клиентов. Непростые глаголы имеют для меня больше смысла (поскольку мы не хотим, чтобы DELETE попадало на сервер, если сервер не говорит, что это приветствуется). Я тоже озадачен требованием предварительной проверки пользовательского заголовка.   -  person apsillers    schedule 19.11.2012
comment
@apsillers, могу ли я быть абсолютно уверен, что правильно понял ваше разъяснение? Насколько я понимаю, вы говорите, что такие «предполетные» запросы не используются для проверки формулировок GET и POST, а только для таких глаголов, как PUT, DELETE и т. д.? (если нет пользовательских заголовков) Если да, то как применяются GET и POST?   -  person Greg Pallis    schedule 19.11.2012
comment
Это верно. В терминах CORS GET и POST называются простыми HTTP-глаголами, и им разрешено обращаться к серверу из разных источников (но браузер может решить после завершения HTTP-запроса, что JS не увидит результат). Здесь может быть полезен заголовок Origin, так как любой источник может успешно отправить запрос GET/POST любому другому источнику, но ответ может быть невидим для JavaScript, если браузер его заблокирует. (Запросам, отличным от GET и POST, не разрешается достигать сервера до тех пор, пока не будет выполнена успешная предварительная проверка OPTIONS, что вы уже понимаете.)   -  person apsillers    schedule 19.11.2012
comment
Таким образом, браузер с поддержкой CORS всегда отправляет запросы GET/POST независимо от источника, но он может отказать JavaScript в доступе к данным ответа в соответствии с политикой того же источника. Вы также можете найти этот мой предыдущий ответ полезным.   -  person apsillers    schedule 19.11.2012
comment
@apsillers - спасибо! С вашей помощью и помощью epascarello я определенно значительно улучшил свое понимание. Мне все еще немного неясна одна деталь — почему Chrome отправляет заголовок Origin с запросом GET? Мне это кажется немного неэффективным; Теперь я уверен, что никакие серверы ничего не делают с этой информацией (поскольку это GET, а не OPTIONS), и, предположительно, Chrome в любом случае имеет доступ к Origin, когда приходит ответ. Но, возможно, Chrome не имеет доступа к этой информации любым удобным способом, и это вопрос административного удобства.   -  person Greg Pallis    schedule 20.11.2012
comment
Ага! Это вещь CRSF. Да, думаю, теперь я это полностью понимаю. Большое спасибо!   -  person Greg Pallis    schedule 20.11.2012


Ответы (1)


Так работает CORS. По сути, это рукопожатие, означающее «да, вы можете поговорить со мной». Вы не можете знать, возможно ли это, если не связаться с третьей стороной.

Ниже приведена часть раздела Preflighted_requests статьи MDN:

В отличие от простых запросов (описанных выше), «предварительные» запросы сначала отправляют заголовок запроса HTTP OPTIONS ресурсу в другом домене, чтобы определить, безопасно ли отправлять фактический запрос. Межсайтовые запросы проходят предварительную проверку таким образом, поскольку они могут иметь последствия для пользовательских данных. В частности, запрос проходит предварительную проверку, если:

Он использует методы, отличные от GET или POST. Кроме того, если POST используется для отправки данных запроса с Content-Type, отличным от application/x-www-form-urlencoded, multipart/form-data или text/plain, например. если запрос POST отправляет полезную нагрузку XML на сервер с использованием application/xml или text/xml, то запрос проходит предварительную проверку. Он устанавливает пользовательские заголовки в запросе (например, запрос использует заголовок, такой как X-PINGOTHER)

person epascarello    schedule 19.11.2012