Preflight request что это
XMLHttpRequest: кросс-доменные запросы
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/fetch-crossorigin.
Обычно запрос XMLHttpRequest может делать запрос только в рамках текущего сайта. При попытке использовать другой домен/порт/протокол – браузер выдаёт ошибку.
Существует современный стандарт XMLHttpRequest, он ещё в состоянии черновика, но предусматривает кросс-доменные запросы и многое другое.
Большинство возможностей этого стандарта уже поддерживаются всеми браузерами, но увы, не в IE9-.
Впрочем, частично кросс-доменные запросы поддерживаются, начиная с IE8, только вместо XMLHttpRequest нужно использовать объект XDomainRequest.
Кросс-доменные запросы
Разберём кросс-доменные запросы на примере кода:
Контроль безопасности
Кросс-доменные запросы проходят специальный контроль безопасности, цель которого – не дать злым хакерам™ завоевать интернет.
Серьёзно. Разработчики стандарта предусмотрели все заслоны, чтобы «злой хакер» не смог, воспользовавшись новым стандартом, сделать что-то принципиально отличное от того, что и так мог раньше и, таким образом, «сломать» какой-нибудь сервер, работающий по-старому стандарту и не ожидающий ничего принципиально нового.
Давайте, на минуточку, вообразим, что появился стандарт, который даёт, без ограничений, возможность делать любой странице HTTP-запросы куда угодно, какие угодно.
Как сможет этим воспользоваться злой хакер?
Он сделает свой сайт, например http://evilhacker.com и заманит туда посетителя (а может посетитель попадёт на «злонамеренную» страницу и по ошибке – не так важно).
Спецификация CORS налагает специальные ограничения на запросы, которые призваны не допустить подобного апокалипсиса.
Запросы в ней делятся на два вида.
Простыми считаются запросы, если они удовлетворяют следующим двум условиям:
«Непростыми» считаются все остальные, например, запрос с методом PUT или с заголовком Authorization не подходит под ограничения выше.
Принципиальная разница между ними заключается в том, что «простой» запрос можно сформировать и отправить на сервер и без XMLHttpRequest, например при помощи HTML-формы.
То есть, злой хакер на странице http://evilhacker.com и до появления CORS мог отправить произвольный GET-запрос куда угодно. Например, если создать и добавить в документ элемент
Комментарии
Предварительный запрос файла
Preflight File Request Операция запрашивает правила общего доступа к ресурсам в разных источниках (CORS) для службы файлов Azure перед отправкой фактического запроса. Веб-браузер или другой агент пользователя отправляют предварительный запрос, где указывается исходный домен, метод и заголовки для фактического запроса, который агент хочет сделать. Если CORS включена для файлов Azure, то служба «файлы Azure» оценивает Предпечатный запрос по правилам CORS, настроенным владельцем учетной записи посредством задания свойств службы файлов, и принимает или отвергает запрос.
Доступность протокола
Включенный протокол общей папки | Доступно |
---|---|
SMB | |
NFS |
Запрос
HTTP-команда | Универсальный код ресурса (URI) запроса | параметр «Версия HTTP» | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
OPTIONS | http://.file.core.windows.net/ Обратите внимание, что URI должен всегда включать косую черту (/) для отделения имени узла от частей пути и запроса URI. В случае этой операции часть пути URI может быть пустой или может указывать на любой ресурс службы файлов. Если ресурс службы файлов является общим ресурсом или каталогом, параметр запроса рестипе является обязательным. На момент подачи предварительного запроса ресурс может существовать, а может и отсутствовать. Предварительный запрос оценивается на уровне службы по правилам CORS службы, поэтому наличие или отсутствие имени ресурса не влияет на эту операцию. Параметры универсального кода ресурса (URI)Заголовки запросовВ следующей таблице перечислены обязательные и необязательные заголовки запросов.
Текст запросаОтветОтвет включает код состояния HTTP и набор заголовков ответа. Код состоянияУспешная операция возвращает код состояния 200 (ОК). Заголовки ответовОтвет для этой операции включает следующие заголовки. Ответ может также включать дополнительные стандартные заголовки HTTP. Все стандартные заголовки соответствуют спецификации протокола HTTP/1.1.
Текст ответаАвторизацияPreflight File Request Операция всегда выполняется анонимно. Он не требует авторизации и не учитывает учетные данные, если они предоставлены. Пример запроса и ответаВ следующем примере выполняется отправка предварительного запроса для источника www.contoso.com, в котором в качестве метода запроса задан PUT, а заголовками запроса являются content-type и accept. Ответ указывает, что CORS включен в этой службе и что предварительный запрос соответствует правилу CORS. RemarksЕсли CORS не включен или нет правила CORS, которому соответствует предварительный запрос, то служба отправляет код состояния 403 (Запрещено). В этом случае счет за запрос выставлен не будет. Если запрос OPTIONS сформирован неправильно, то в ответ служба отправит код состояния 400 (Неправильный запрос), и запрос не будет включен в счет. Примером неверно сформированного запроса является тот, который не содержит обязательные Origin Access-Control-Request-Method заголовки и. Обратите внимание, что предварительные запросы — это механизм использования функций CORS службы хранилища, связанной с какой-либо учетной записью хранилища. Предварительный запрос не нацелен на конкретный ресурс. Предварительный запрос очередиОперация Preflight Queue Request запрашивает правила общего доступа к ресурсам независимо от источника (CORS) для службы очередей перед отправкой самого запроса. Веб-браузер или другой агент пользователя отправляют предварительный запрос, где указывается исходный домен, метод и заголовки для фактического запроса, который агент хочет сделать. Если для служба очередей включен CORS, то служба очередей оценивает Предпечатный запрос по правилам CORS, настроенным владельцем учетной записи с помощью задания свойств службы очередей, и принимает или отвергает запрос. ЗапросОбратите внимание, что URI должен всегда включать косую черту (/) для отделения имени узла от частей пути и запроса URI. В случае выполнения этой операции часть пути URI может быть пустой или может указывать любой ресурс очереди. На момент подачи предварительного запроса ресурс может существовать, а может и отсутствовать. Предварительный запрос оценивается на уровне службы по правилам CORS службы, поэтому наличие или отсутствие имени ресурса не влияет на эту операцию. Параметры URIЗаголовки запросовВ следующей таблице перечислены обязательные и необязательные заголовки запросов.
Текст запросаОтветОтвет включает код состояния HTTP и набор заголовков ответа. Код состоянияУспешная операция возвращает код состояния 200 (ОК). Сведения о кодах состояния см. в разделе состояние и коды ошибок. Заголовки откликовОтвет для этой операции включает следующие заголовки. Ответ может также включать дополнительные стандартные заголовки HTTP. Все стандартные заголовки соответствуют спецификации протокола HTTP/1.1. Текст ответаАвторизацияPreflight Queue Request Операция всегда выполняется анонимно. Он не требует авторизации и не учитывает учетные данные, если они предоставлены. Пример запроса и ответаОтвет указывает, что CORS включен в этой службе и что предварительный запрос соответствует правилу CORS. RemarksЕсли CORS не включен или нет правила CORS, которому соответствует предварительный запрос, то служба отправляет код состояния 403 ( Forbidden ). В этом случае счет за запрос выставлен не будет. Обратите внимание, что предварительные запросы — это механизм использования функций CORS службы хранилища, связанной с какой-либо учетной записью хранилища. Предварительный запрос не нацелен на конкретный ресурс. Безопасность наглядно: CORSAug 27, 2020 · 8 min read
Во фронтенде часто требуется отобразить данные, которые хранятся в другом месте. Перед этим браузер должен направить запрос серверу: клиент отправляет HTTP-запрос со всей информацией, которая нужна серверу, чтобы вернуть данные. Что произошло? Мы отправили такой же запрос, но на этот раз браузер выдал странную ошибку. Мы только что увидели CORS в действии. Давайте разберёмся, почему возникла эта ошибка, и что она означает. Правило одинакового источника (Same-Origin Policy)Ресурс считается принадлежащим к другому источнику (cross-origin), если он располагается на другом домене/поддомене, протоколе или порте. Это, конечно, здорово, но для чего правило одинакового источника вообще существует? Представим, что это правило не работает, а вы случайно нажали на какую-то вирусную ссылку, которую прислала ваша тётушка на Фейсбуке. Ссылка перенаправляет вас на мошеннический сайт, который с помощью фрейма загружает интерфейс сайта вашего банка и успешно залогинивает вас с помощью сохранённых куки. Разработчики этого мошеннического сайта сделали так, чтобы он имел доступ к фрейму и мог взаимодействовать с DOM сайта вашего банка — так они смогут переводить деньги на свой счёт от вашего имени. Да, это огромная угроза безопасности — мы ведь не хотим, чтобы кто угодно имел доступ к чему угодно. К счастью, здесь приходит на помощь правило одинакового источника: оно гарантирует, что мы можем получить доступ только к ресурсам из того же самого источника. Но какое отношение всё это имеет к CORS? CORS на стороне клиентаНесмотря на то, что правило одинакового источника применяется исключительно к скриптам, браузеры распространили его и на JavaScript-запросы: по умолчанию можно получить доступ к ресурсам только из одинакового источника. Но нам ведь часто нужно обращаться к ресурсам из других источников… Может, тогда фронтенду стоит взаимодействовать с API на бэкенде, чтобы загружать данные? Чтобы обеспечить безопасность запросов к другим источникам, браузеры используют механизм под названием CORS. Аббревиатура CORS расшифровывается как Cross-Origin Resource Sharing (Технология совместного использования ресурсов между разными источниками). Несмотря на то, что браузеры не позволяют получать доступ к ресурсам из разных источников, можно использовать CORS, чтобы внести небольшие коррективы в эти ограничения и при этом быть уверенным, что доступ будет безопасным. Пользовательские агенты (к примеру, браузеры) на основе значений определённых заголовков для CORS в HTTP-запросе могут проводить запросы к другим источникам, которые без CORS были бы заблокированы. Когда происходит запрос к другому источнику, клиент автоматически подставляет дополнительный заголовок Origin в HTTP-запрос. Значение этого заголовка отражает источник запроса. Чтобы браузер разрешил доступ к ресурсам из другого источника, он должен получить определённые заголовки в ответе от сервера, которые указывают, разрешает ли сервер запросы из других источников. CORS на стороне сервераДа, теперь CORS выдаёт эту печально известную ошибку, которая иногда всех нас так расстраивает. Но сейчас нам понятно, какой смысл она несет. Предварительные запросыСуществует два типа CORS-запросов: простые и предварительные. Тип запроса зависит от хранящихся в нём значений (не волнуйтесь, здесь не надо будет ничего запоминать).
Но что означают и почему существуют “предварительные запросы”? Перед отправкой текущего запроса клиент сначала генерирует предварительный запрос: в своих заголовках Access-Control-Request-* он содержит информацию о текущем запросе. Это позволяет серверу узнать метод, дополнительные заголовки и другие параметры запроса, который браузер пытается отправить. Сервер получает этот предварительный запрос и отправляет обратно пустой HTTP-ответ с CORS-заголовками сервера. Браузер в свою очередь получает предварительный ответ (только CORS-заголовки) и проверяет, разрешён ли HTTP-запрос. Если всё в порядке, браузер посылает текущий запрос на сервер, а тот в ответ присылает данные, которые мы запрашивали. Если же возникает проблема, CORS блокирует предварительный запрос, а текущий вообще уже не будет отправлен. Предварительный запрос — отличный способ уберечь нас от получения доступа или изменения ресурсов на серверах, у которых (пока что) не настроены правила CORS. Сервера защищены от потенциально нежелательных запросов из других источников. Учётные данныеКуки, заголовки авторизации, TLS-сертификаты по умолчанию включены только в запросы из одинакового источника. Однако нам может понадобиться использовать учётные данные и в запросах из разных источников. Возможно, мы захотим включить куки в запрос, который сервер сможет использовать для идентификации пользователя. Готово — теперь мы можем включать учётные данные в запрос из другого источника. Думаю, мы все согласимся с тем, что появление ошибок CORS порой расстраивает, но, тем не менее, здорово, что CORS позволяет безопасно отправлять запросы из разных источников в браузере — считаю, что мы должны любить эту технологию чуточку сильнее 🙂 Разумеется, о правиле одинакового источника и CORS можно рассказать гораздо больше, но я просто не смогу уместить всё это в одной статье. К счастью, ресурсов много (к примеру, спецификация W3) — вам будет к чему обратиться, если захотите подробнее изучить эту тему. Политика общего происхождения и CORS: визуальное руководствоДоброго времени суток, друзья! Представляю вашему вниманию перевод статьи «CS Visualized: CORS» автора Lydia Hallie.
Отлично! Мы только что отправили запрос на сервер и получили в ответ данные в формате JSON.
Что случилось? Мы отправили точно такой же запрос, но на этот раз браузер показывает какую-то ошибку. Мы наблюдаем CORS в действии. Почему возникла данная ошибка и что она означает? Политика общего происхожденияИсточник является другим, когда он расположен в другом (под)домене, протоколе или порте.
Круто, но зачем нужна ПОП? Предположим, что ее не существует, и вы случайно кликаете по вирусной ссылке, которую прислала ваша тетя в Facebook. Данная ссылка перенаправляет вас на «вредоносный сайт», имеющий встроенный iframe, который загружает сайт вашего банка и успешно авторизуется там с помощью куки. Разработчики «злого сайта» позаботились о том, чтобы он имел доступ к iframe и мог взаимодействовать с содержимым DOM сайта вашего банка для перечисления денежных средств на свой аккаунт от вашего имени.
Да уж… это серьезная проблема безопасности. Мы не хотим, чтобы кто-нибудь имел доступ к чему-либо без нашего ведома. К счастью, существует ПОП. Эта политика ограничивает доступ к ресурсам из других источников.
Хорошо, но… как это работает? CORS на стороне клиентаНесмотря на то, что ПОП применяется только к скриптам, браузеры «расширяют» ее до любых JavaScript-запросов: по умолчанию мы имеем доступ только к ресурсам из одного источника.
Хм, но… у нас часто возникает необходимость получить ресурсы из другого источника. Возможно, нашему фронтенду нужно обратиться к серверному прикладному интерфейсу для загрузки данных. Для безопасного получения ресурсов из других источников браузеры реализуют механизм под названием CORS. CORS расшифровывается как Cross-Origin Resource Sharing (совместное использование ресурсов). Хотя браузеры запрещают получение ресурсов из других источников, мы можем использовать CORS для изменения этого ограничения, оставаясь при этом в безопасности. Пользовательские агенты (браузеры) могут использовать механизм CORS для разрешения запросов между разными источниками, которые в противном случае были бы заблокированы, на основе некоторых заголовков HTTP-ответа.
Для того, чтобы браузер разрешил получение ресурсов из другого источника, в ответе сервера также должен содержаться определенный заголовок. CORS на стороне сервераЗначение данного заголовка определяет, какие источники могут получать наши ресурсы.
Да, CORS заблокировал доступ к ресурсам. CORS позволяет указать * в качестве значения разрешенных источников. Это означает, что ресурсы будут доступны любым источникам, так что будьте осторожны. Access-Control-Allow-Origin — это один из многих заголовков, которые мы можем установить. Разработчик серверной части может настраивать CORS для разрешения (запрета) конкретных запросов.
В данном случае разрешены только запросы, отправленные с помощью методов GET, POST или PUT. Другие методы, такие как PATCH или DELETE будут заблокированы. Говоря о запросах, отправленных с помощью методов PUT, PATCH и DELETE, CORS обрабатывает их особым образом. Эти «непростые» запросы иногда называют предварительными (preflight). Предварительные запросыCORS работает с двумя типами запросов: простыми и предварительными. То, каким является запрос, зависит от некоторых его значений. Запрос является простым, если он отправлен с помощью методов GET или POST и не содержит дополнительных заголовков. Любой другой запрос является предварительным. Хорошо, но что означает предварительный запрос и зачем нужны такие запросы? Перед отправкой фактического запроса, клиент направляет серверу предварительный запрос с информацией о фактическом запросе: о его методе, дополнительных заголовках, включая Access-Control-Request-* и т.д.
Сервер получает предварительный запрос и отправляет пустой предварительный ответ, содержащий CORS-заголовки. Браузер получает предварительный ответ и проверяет, будет ли разрешен фактический запрос.
Если да, то браузер отправляет фактический запрос и получает данные в ответ.
Если нет, CORS заблокирует предварительный запрос и фактический запрос не будет отправлен. Предварительные запросы — это отличный способ предотвратить доступ и изменение ресурсов на сервере. Это защищает сервер от потенциально нежелательных запросов из других источников. Для уменьшения количества повторных запросов мы можем закэшировать предварительный ответ посредством добавления заголовка Access-Control-Max-Age в CORS-запрос. Это позволяет избежать повторного направления предварительного запроса. Полномочия (credentials)Куки, заголовки авторизации и сертификаты TLS по умолчанию устанавливаются только для запросов из одного источника. Однако у нас может возникнуть необходимость использовать эти полномочия в запросе из другого источника. Возможно, мы хотим включить в запрос куки, которые сервер может использовать для идентификации пользователя. Если мы хотим включить куки и другие заголовки авторизации в наш запрос из другого источника, нам нужно присвоить полю withCredentials значение true в запросе и добавить заголовок Access-Control-Allow-Credentials в ответ.
Готово, теперь мы можем включать полномочия в наши запросы из другого источника. Надеюсь, статья была вам полезной. Благодарю за внимание.
|