Безопасное совместное использование ресурсов из разных источников
Политика браузера в отношении одного и того же источника блокирует чтение ресурса из другого источника. Этот механизм не позволяет вредоносным сайтам читать данные других сайтов, но также предотвращает законное использование.
Современные веб-приложения часто хотят получать ресурсы из другого источника, например, получать данные 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
, чтобы указать продолжительность в секундах кэширования результатов предварительной проверки. Это позволяет клиенту отправлять несколько сложных запросов без необходимости повторять предполетный запрос.