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

Безопасный обмен ресурсами из разных источников.

Mariko Kosaka

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

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

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

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

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

Браузер и сервер могут обмениваться данными по сети, используя протокол HTTP (Hypertext Transfer Protocol ). 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 , указывающий продолжительность кэширования результатов предварительной проверки в секундах. Это позволяет клиенту отправлять несколько сложных запросов без необходимости повторного выполнения предварительного запроса.