CORS и заголовок ответа Access-Control-Allow-Origin

Источник: «CORS and the Access-Control-Allow-Origin response header»
В этой статье мы объясним, что такое заголовок ответа Access-Control-Allow-Origin в отношении CORS и как он является частью реализации CORS.

Спецификация совместного использования ресурсов между источниками (CORS) обеспечивает контролируемое смягчение политики единого источника (Same-origin policy) для HTTP-запросов к одному домену веб-сайтов от другого за счёт использования набора HTTP заголовков. Браузеры разрешают доступ к ответам на запросы из разных источников на основе этих инструкций в заголовке.

Что такое заголовок ответа Access-Control-Allow-Origin

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

Реализация простого совместного использования ресурсов между источниками

Спецификация совместного использования ресурсов между источниками (CORS) предписывает обмен содержимым заголовков между веб-серверами и браузерами, который ограничивает источники запросов веб-ресурсов за пределами исходного домена. Спецификация CORS определяет набор заголовков протокола, из которых Access-Control-Allow-Origin является наиболее важным. Этот заголовок возвращается сервером, когда веб-сайт запрашивает междоменный ресурс с заголовком Origin, добавленным браузером.

Предположим, что веб-сайт с источником normal-website.com вызывает следующий междоменный запрос:

GET /data HTTP/1.1
Host: robust-website.com
Origin : https://normal-website.com

Сервер на сайте robust-website.com возвращает следующий ответ:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com

Браузер позволит коду, запущенному на normal-website.com получить доступ к ответу, потому что источники совпадают.

Спецификация Access-Control-Allow-Origin допускает несколько источников, значение null или подстановочный знак *. Однако ни один браузер не поддерживает несколько источников, и существуют ограничения на использование подстановочного знака *.

Обработка запросов ресурсов из разных источников с учётными данными

Поведение по умолчанию для запроса ресурсов из разных источников заключается в том, что запросы передаются без учётных данных, таких как файлы cookie и заголовок авторизации. Однако междоменный сервер может разрешить чтение ответа, когда ему передаются учётные данные, установив для заголовка CORS Access-Control-Allow-Credentials значение true. Теперь, если запрашивающий веб-сайт использует JavaScript, чтобы объявить, что он отправляет файлы cookie с запросом:

GET /data HTTP/1.1
Host: robust-website.com
...
Origin: https://normal-website.com
Cookie: JSESSIONID=<value>

И ответ на запрос:

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

Затем браузер разрешит запрашивающему веб-сайту прочитать ответ, потому что для заголовка ответа Access-Control-Allow-Credentials установлено значение true. В противном случае браузер не разрешит доступ к ответу.

Ослабление спецификации CORS с помощью подстановочных знаков

Заголовок Access-Control-Allow-Origin поддерживает подстановочные знаки. Например:

Access-Control-Allow-Origin: *

Обратите внимание, что подстановочные знаки нельзя использовать внутри любого другого значения. Например, следующий заголовок не валидный:

Access-Control-Allow-Origin: https://*.normal-website.com

К счастью, с точки зрения безопасности использование подстановочного знака ограничено в спецификации, поскольку вы не можете комбинировать подстановочный знак с передачей учётных данных между источниками (аутентификация, файлы cookie или сертификаты на стороне клиента). Следовательно, междоменный ответ сервера вида:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Не разрешён, так как это было бы небезопасно, так как любой аутентифицированный контент на целевом сайте будет доступен всем.

Учитывая эти ограничения, некоторые веб-серверы динамически задают заголовки Access-Control-Allow-Origin на основе указанного клиентом источника. Это обходной путь для ограничений CORS, который не является безопасным.

Предполётные проверки

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

Например, это предполётный запрос, который пытается использовать метод PUT вместе с настраиваемым заголовком запроса под названием Special-Request-Header:

OPTIONS /data HTTP/1.1
Host: <some website>
...
Origin: https://normal-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-Header

Сервер может вернуть ответ, подобный следующему:

HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240

В этом ответе устанавливаются разрешённые методы (PUT, POST и OPTIONS) и разрешённые заголовки запроса (Special-Request-Header). В этом конкретном случае междоменный сервер также разрешает отправку учётных данных, а заголовок Access-Control-Max-Age определяет максимальный период времени для кэширования ответа перед отправкой для повторного использования. Если методы запроса и заголовки разрешены (как в этом примере), то браузер обрабатывает запрос из разных источников обычным образом. Предполётные проверки добавляют к междоменному запросу дополнительный HTTP-запрос туда и обратно, поэтому они увеличивают накладные расходы при просмотре.

Защищает ли CORS от CSRF

CORS не обеспечивает защиту от атак с подделкой межсайтовых запросов (CSRF), это распространённое заблуждение.

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

Существуют различные способы выполнения CSRF-атак без использования CORS, включая простые HTML формы и междоменные ресурсы.

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

Дополнительные материалы

Предыдущая Статья

JavaScript: Что такое Промисы / Promise

Следующая Статья

JavaScript: Полное руководство по обработке ошибок