Совместное использование ресурсов между источниками (CORS)

Безопасное совместное использование ресурсов из разных источников

Mariko Kosaka

Политика браузера в отношении одного и того же источника блокирует чтение ресурса из другого источника. Этот механизм не позволяет вредоносным сайтам читать данные других сайтов, но также предотвращает законное использование.

Современные веб-приложения часто хотят получать ресурсы из другого источника, например, получать данные JSON из другого домена или загружать изображения с другого сайта в элемент <canvas> . Это могут быть общедоступные ресурсы, которые должны быть доступны для чтения всем, но политика одного и того же происхождения блокирует их использование. Разработчики исторически использовали обходные пути, такие как JSONP .

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

Как запрос ресурса работает в Интернете?

запрос и ответ
Иллюстрированный запрос клиента и ответ сервера.

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

Заголовок HTTP согласовывает обмен сообщениями между клиентом и сервером и используется для определения доступа. И запрос браузера, и ответное сообщение сервера делятся на заголовок и тело .

Информация о сообщении, такая как тип сообщения или кодировка сообщения. Заголовок может включать в себя различную информацию , выраженную в виде пар ключ-значение. Заголовок запроса и заголовок ответа содержат разную информацию.

Пример заголовка запроса

Accept: text/html
Cookie: Version=1

Этот заголовок эквивалентен сообщению: «Я хочу получить HTML в ответ. Вот файл cookie, который у меня есть».

Пример заголовка ответа

Content-Encoding: gzip
Cache-Control: no-store

Этот заголовок эквивалентен сообщению: «Данные в этом ответе закодированы с помощью gzip. Не кэшируйте это».

Тело

Само сообщение. Это может быть обычный текст, двоичное изображение, JSON, HTML или многие другие форматы.

Как работает CORS?

Политика одного и того же источника предписывает браузеру блокировать запросы из разных источников. Когда вам нужен общедоступный ресурс из другого источника, сервер, предоставляющий ресурсы, сообщает браузеру, что источник, отправляющий запрос, может получить доступ к его ресурсу. Браузер запоминает это и разрешает совместное использование ресурсов из разных источников для этого ресурса.

Шаг 1: запрос клиента (браузера)

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

Шаг 2: ответ сервера

Когда сервер видит этот заголовок и хочет разрешить доступ, он добавляет к ответу заголовок Access-Control-Allow-Origin указывающий источник запроса (или * , чтобы разрешить любой источник).

Шаг 3: браузер получает ответ

Когда браузер видит этот ответ с соответствующим заголовком Access-Control-Allow-Origin , он передает данные ответа клиентскому сайту.

Поделитесь учетными данными с CORS

По соображениям конфиденциальности CORS обычно используется для анонимных запросов, в которых запрашивающий не идентифицирован. Если вы хотите отправлять файлы cookie при использовании CORS, которые могут идентифицировать отправителя, вам необходимо добавить в запрос и ответ дополнительные заголовки.

Запрос

Добавьте credentials: 'include' к параметрам выборки, как показано в следующем примере. Сюда входит файл cookie со следующим запросом:

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})

Ответ

Access-Control-Allow-Origin должно быть установлено определенное происхождение (без подстановочного знака с использованием * ), а Access-Control-Allow-Credentials должно быть установлено значение true .

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true

Предварительные запросы для сложных HTTP-вызовов

Когда веб-приложение выполняет сложный HTTP-запрос, браузер добавляет предварительный запрос в начало цепочки запросов.

Спецификация CORS определяет сложный запрос следующим образом:

  • Запрос, использующий методы, отличные от GET, POST или HEAD.
  • Запрос, включающий заголовки, отличные от Accept , Accept-Language или Content-Language .
  • Запрос с заголовком Content-Type , отличным от application/x-www-form-urlencoded , multipart/form-data или text/plain .

Браузеры автоматически создают все необходимые предполетные запросы и отправляют их перед фактическим сообщением с запросом. Предварительный запрос представляет собой запрос OPTIONS , как показано в следующем примере:

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE

На стороне сервера приложение, получающее запрос, отвечает на предполетный запрос информацией о методах, которые приложение принимает от этого источника:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS

Ответ сервера также может включать заголовок Access-Control-Max-Age , чтобы указать продолжительность в секундах кэширования результатов предварительной проверки. Это позволяет клиенту отправлять несколько сложных запросов без необходимости повторять предполетный запрос.