Прежде чем мы перейдем к совместному использованию ресурсов между источниками, нам нужно сделать шаг назад, чтобы понять, что такое происхождение? Более того, нам нужно понять, что такое политика одного и того же происхождения (SOP) и политика перекрестного происхождения (COP).

Надеюсь, это поможет вам позже, когда мы перейдем к CORS (обмен ресурсами между источниками).

Давайте начнем с ответа на наш первый вопрос, что такое происхождение? Источник определяется этими тремя частями: схемой (протоколом), именем хоста или хостом (доменом) и портом.

имя хоста и порт формируют то, что известно как «авторитет», который обозначается символом «://». часть - власть.

Правило звучит так: два происхождения считаются одним и тем же, если все три части совпадают.

Примеры

Эти два узла считаются имеющими одно и то же происхождение, поскольку все они имеют одинаковую схему (HTTPS) и имя хоста (example.com), а разные пути не имеют значения, поскольку они не являются частью источника.

"https://example.com/example/1" https://example.com/example/2

ПРИМЕЧАНИЕ. Несмотря на то, что порт не указан явно, он все равно присутствует, но подразумевается браузером: 80 для «http://» и «ws://», 443 для «https: //» и «wss://», 21 для «ftp://». поэтому, если вы укажете его явно и выполните поиск «https://example.com:443/example/1», он не даст сбоя, если только это не веб-сайт с необычной настройкой.

Они не одного происхождения, потому что отличаются портом.

"http://example.com:8080/example/1" http://example.com/example/1

Они не одного происхождения, поскольку используют разные имена хостов.

"http://www.example.com/example/1" http://example.com/example/1

Политика того же происхождения

Политика того же источника — это критически важный механизм безопасности, который ограничивает взаимодействие документа или сценария, загруженного из одного источника, с ресурсом из другого источника. разработан в ответ на атаки «подделка межсайтовых запросов» (CSRF или, альтернативно, XSRF).

Политика одного и того же источника контролирует взаимодействие между двумя разными источниками. Эти взаимодействия обычно делятся на три категории:

  1. Запись из разных источников обычно разрешена. Примерами являются ссылки, перенаправления и отправка форм. Для некоторых HTTP-запросов требуется «предварительный запрос» (объяснение содержится в разделе политики перекрестного происхождения).
  2. встраивание из разных источников обычно разрешено. таких как встраивание тегов ‹img›, тегов ‹script›, тегов CSS ‹link›, мультимедиа, воспроизводимых с помощью ‹video› или ‹audio›, или даже тегов ‹iframe›, сайты могут использовать заголовок «X-Frame-Options» для предотвратить кадрирование из разных источников (означает рендеринг страницы из разных источников).
  3. Чтение из разных источников обычно запрещено.

Вы можете подумать, что злоумышленник может использовать категорию #2 для проведения атаки CSRF. Поскольку вы можете включить URL-адрес в ‹img src=”…”/› или ‹script src="…”/›, именно здесь на сцену выходят билеты транзакций или токены CSRF. Подробнее здесь:

https://stackoverflow.com/a/29167709 и https://stackoverflow.com/a/27294846

унаследованное происхождение

Скрипты, выполняемые со страниц с URL-адресом «about:blank» или «javascript:», наследуют источник документа, содержащего этот URL-адрес, поскольку эти типы URL-адресов не содержат информации об исходном сервере.

Например, about:blank часто используется как URL-адрес нового пустого окна, в которое родительский сценарий записывает содержимое (например, с помощью механизма Window.open()). Если это окно также содержит JavaScript, этот сценарий унаследует то же происхождение, что и сценарий, который его создал.

Исключения в Internet Explorer

В Internet Explorer есть два основных исключения из политики одного и того же источника:

Доверенные зоны

Если оба домена находятся в зоне высокого доверия (например, домены корпоративной интрасети), то ограничения одного и того же происхождения не применяются.

Порт

IE не включает порт в проверки того же происхождения. Таким образом, «https://example.com:81/» и «https://company.com/» считаются одним и тем же источником и не применяются никакие ограничения.

Эти исключения нестандартны и не поддерживаются ни в одном другом браузере.

Происхождение файлов

Современные браузеры обычно рассматривают происхождение файлов, загруженных с использованием схемы «file:///», как «непрозрачное происхождение». Это означает, что если файл включает в себя другие файлы из той же папки, предполагается, что они не происходят из одного и того же источника и могут вызывать ошибки CORS, но обратите внимание, что происхождение файлов зависит от реализации, поэтому некоторые браузеры могут обрабатывать файлы в том же каталоге или подкаталоге, что и тот же источник, даже если это имеет последствия для безопасности.

Политика перекрестного происхождения

Совместное использование ресурсов между источниками (CORS) — это механизм на основе HTTP-заголовков, который позволяет серверу указывать любые источники, кроме своего собственного, из которых браузер должен разрешать загрузку ресурсов.

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

Мы знаем, что из соображений безопасности браузеры ограничивают HTTP-запросы из разных источников, инициированные скриптами. Например, «XMLHttpRequest» и «Fetch API» следуют политике одного и того же источника. Это означает, что веб-приложение, использующее эти API-интерфейсы, может запрашивать ресурсы только из того же источника, из которого было загружено приложение, если только ответ из других источников не включает правильные заголовки CORS.

XMLHttpRequest будет отправлять и получать заголовки CORS от имени разработчика.

С Fetch API вам нужно изменить «режим» для вашего запроса на «cors» вместо стандартного «no-cors».

Кроме того, если вы хотите, чтобы ваш браузер не игнорировал (файлы cookie, записи HTTP-аутентификации и клиентские сертификаты TLS), поступающие из ответа, вам необходимо установить для «учетных данных» значение «включать», а также аналог в XMLHttpRequest, который Свойство XMLHttpRequest.withCredentials.

Для запросов, созданных с помощью конструктора, отличного от конструктора «Fetch API», которым является «fetch()», будет установлен режим «cors». например, запросы, созданные с помощью конструктора Request().

Сбои CORS приводят к ошибкам, но из соображений безопасности сведения об ошибке недоступны для JavaScript. Все, что код знает, это то, что произошла ошибка. Единственный способ определить, что именно пошло не так, — посмотреть подробности в консоли браузера.

Предварительный запрос

Запрос предварительной проверки CORS — это запрос CORS, который проверяет, понят ли протокол CORS и знает ли сервер, используя определенные методы и заголовки, а также чтобы определить, безопасно ли отправлять фактический запрос.

Это запрос «параметров», использующий три заголовка HTTP-запроса: «Access-Control-Request-Method», «Access-Control-Request-Headers» и заголовок «Origin».

Предпечатный запрос отправляется браузером автоматически. он отправляется, если фактический запрос не является «простым запросом».

простые запросы

Некоторые запросы CORS не запускают предварительный запрос CORS. Они называются простыми запросами.

Запрос является простым запросом, когда он соответствует всем следующим условиям:

  1. один из допустимых методов: GET, HEAD или POST.
  2. Единственными заголовками, которые разрешено устанавливать вручную, являются: Accept, Accept-Language, Content-Language, Content-Type и Range (только с простым значением заголовка диапазона).
  3. Единственные комбинации типа/подтипа, разрешенные для типа носителя, указанного в заголовке Content-Type: «application/x-www-form-urlencoded», «multipart/form-data», «text/plain»
  4. Если запрос сделан с использованием объекта XMLHttpRequest, прослушиватели событий не регистрируются для объекта, возвращаемого свойством XMLHttpRequest.upload, используемым в запросе; то есть при наличии экземпляра XMLHttpRequest xhr ни один код не вызывал xhr.upload.addEventListener() для добавления прослушивателя событий для отслеживания загрузки.
  5. В запросе не используется объект ReadableStream.

Пример простого запроса CORS (без запроса предварительной проверки)

это простейшее использование CORS, хост «foo.example» включает заголовок «Origin» в свой запрос, чтобы указать серверу, что запрос исходит от «https://foo.example/», сервер отвечает с заголовком «Access-Control-Allow-Origin: *» звездочка (*) означает, что запрос может быть получен из любого источника.

Пример запроса CORS (с предварительным запросом)

Давайте посмотрим на полный обмен между клиентом и сервером.

Запрос параметров предварительной проверки клиента:

OPTIONS /index.html HTTP/1.1 
...
...
...
Origin: https://foo.example 
Access-Control-Request-Method: POST 
Access-Control-Request-Headers: X-Custom-Header-One, Content-Type

Заголовок предварительного запроса «Origin» указывает серверу, что при отправке фактического запроса он будет отправлен с «https://foo.example/».

Заголовок предварительного запроса «Access-Control-Request-Method» указывает серверу, что при отправке фактического запроса он будет делать это с помощью метода «POST».

Заголовок предварительного запроса «Access-Control-Request-Headers» указывает серверу, что при отправке фактического запроса он будет делать это с настраиваемыми заголовками «X-MY-CUSTOM-HEADER» и «Content-Type».

Ответ сервера на запрос параметров предварительной проверки:

HTTP/1.1 204 No Content
...
...
... 
Access-Control-Allow-Origin: https://foo.example 
Access-Control-Allow-Methods: POST, GET, OPTIONS 
Access-Control-Allow-Headers: X-Custom-Header-One, Content-Type 
Access-Control-Expose-Headers: * 
Access-control-Allow-Credentials: true 
Access-Control-Max-Age: 86400

Заголовок ответа «Access-Control-Allow-Origin» указывает, что только этому домену разрешен доступ к ресурсу.

Заголовок ответа «Access-Control-Allow-Methods» указывает, что для доступа к ресурсу разрешено использовать только эти HTTP-методы.

Заголовок ответа «Access-Control-Allow-Headers» указывает, какие пользовательские заголовки HTTP можно использовать во время фактического запроса.

Заголовок ответа «Access-Control-Expose-Headers» указывает, какие заголовки ответов могут быть доступны для сценариев, работающих в браузере. (* или звездочка означает все заголовки.)

Заголовок ответа «Access-control-Allow-Credentials» указывает браузеру, следует ли отображать ответ для внешнего интерфейса JavaScript, когда режим учетных данных запроса «включить» (помните свойство выборки учетных данных, мы можем установить для него значение «включить»), если вы опустили этот заголовок ответа, тогда ответ не будет раскрыт, оба конца должны согласиться.

Заголовок ответа «Access-Control-Max-Age» указывает браузеру, как долго ответ на запрос предварительной проверки может кэшироваться без отправки другого запроса предварительной проверки. Значение по умолчанию — 5 секунд. Значение выражается в секундах, поэтому указанное выше значение равно 86400 секунд, что соответствует 24 часам. Браузер использует специальный кэш, отделенный от общего кэша HTTP, которым он управляет. Предварительные ответы никогда не кэшируются в общем кэше HTTP браузера.

ПРИМЕЧАНИЕ. Каждый браузер имеет максимальное внутреннее значение, которое имеет приоритет, когда «Access-Control-Max-Age» превышает его.

Я просто поцарапал поверхность, это еще не все😅.

Первоначально опубликовано на https://www.linkedin.com.