Skip to content
О сайте Блог Обучение Исследовать узоры Case studies
Содержание
  • Как работает запрос ресурса в Интернете?
    • header
    • body
  • Как работает CORS?
    • Шаг 1: запрос клиента (браузера)
    • Шаг 2: ответ сервера
    • Шаг 3: браузер получает ответ
  • CORS в действии
  • Учетные данные и CORS
    • Запрос
    • Ответ
  • Предварительные запросы для сложных HTTP-вызовов

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

Безопасный доступ к ресурсам на других доменах

Nov 5, 2018
Available in: English, Español, Português, 中文, 日本語 и 한국어
Appears in: Безопасность и надежность
Mariko Kosaka
Mariko Kosaka
TwitterGitHubGlitchHomepage
Содержание
  • Как работает запрос ресурса в Интернете?
    • header
    • body
  • Как работает CORS?
    • Шаг 1: запрос клиента (браузера)
    • Шаг 2: ответ сервера
    • Шаг 3: браузер получает ответ
  • CORS в действии
  • Учетные данные и CORS
    • Запрос
    • Ответ
  • Предварительные запросы для сложных HTTP-вызовов

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

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

Другими словами, существуют общедоступные ресурсы, которые должны быть доступны для чтения всем, но политика одинакового источника блокирует эту возможность. Разработчики использовали обходные пути, такие как JSONP, но благодаря механизму совместного использования ресурсов между разными источниками (CORS) браузер может предоставлять страницам доступ к ресурсам другого домена.

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

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

запрос и ответ
Рисунок: иллюстрированный запрос клиента и ответ сервера

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

HTTP-заголовок используется для согласования типа обмена сообщениями между клиентом и сервером и применяется для определения доступа. И запрос браузера, и ответное сообщение сервера разделены на две части: header (заголовок) и body (тело):

header #

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

Важно отметить, что заголовки не могут содержать комментарии.

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

Accept: text/html
Cookie: Version=1

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

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

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

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

body #

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

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

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

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

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

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

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

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

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

CORS в действии #

Вот крошечный веб-сервер, использующий Express.

Первая конечная точка (строка 8) не имеет установленного заголовка ответа, она просто отправляет файл в ответ.

  • Откройте DevTools, нажав Control+Shift+J (или Command+Option+J, если у вас Mac). - Откройте DevTools, нажав Control+Shift+J (или Command+Option+J, если у вас Mac).

  • Перейдите на вкладку Консоль.

  • Попробуйте следующую команду:

fetch('https://cors-demo.glitch.me/', {mode:'cors'})

Вы должны увидеть сообщение об ошибке:

request has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header
is present on the requested resource.

Вторая конечная точка (строка 13) отправляет тот же файл в ответ, но добавляет в заголовок Access-Control-Allow-Origin: *. С консоли наберите:

fetch('https://cors-demo.glitch.me/allow-cors', {mode:'cors'})

На этот раз ваш запрос не должен блокироваться.

Учетные данные и CORS #

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

Запрос #

Добавьте 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 для указания продолжительности кеширования результатов предварительного запроса (в секундах), чтобы клиенту не нужно было делать предварительный запрос каждый раз при отправке сложного запроса.

Безопасность
Последнее обновление: Nov 5, 2018 — Улучшить статью
Return to all articles
Поделиться
подписаться

Contribute

  • Сообщить об ошибке
  • Просмотреть исходный код

Дополнительная информация

  • developer.chrome.com
  • Новости Chrome
  • Разборы конкретных случаев
  • Подкасты
  • Шоу

Соцсети

  • Twitter
  • YouTube
  • Google Developers
  • Chrome
  • Firebase
  • Google Cloud Platform
  • Все продукты
  • Условия и конфиденциальность
  • Правила сообщества

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies.