Cross-Origin Resource Sharing (CORS) — технология, позволяющая веб-страницам получать содержимое ответа от сервера, расположенного на другом источнике. Под другим источником подразумевается веб-сервер, отличающийся доменом, портом или протоколом, по которому осуществляется запрос.
Современные браузеры по умолчанию не разрешают веб-страницам получать доступ к содержимому ответа, если запрос был отправлен на сервер по порту, домену или протоколу, отличающемуся от порта, домена или протокола самой страницы. Данное правило безопасности называется Same-Origin Policy (SOP). Такая политика была введена с целью предотвращения атак, связанных с несанкционированным доступом к различным ресурсам сайта.
Однако в современном мире web-технологий ситуация, при которой страница отправляет запросы к серверам с другим доменом, довольно частая. Для того, чтобы её грамотно регламентировать, как раз и была создана технология CORS. Она контролирует доступ к содержимому ответа, пришедшему с другого источника, либо сам факт отправки запроса.
Контроль осуществляется через чтение браузером заголовков ответа сервера. Если сервер не прислал в ответе специальные CORS-заголовки с требуемыми значениями, браузер либо не предоставляет странице содержимое ответа сервера, либо блокирует отправку запроса.
Существуют следующие основные CORS-заголовки:
Access-Control-Allow-Origin
— определяет, какому источнику разрешено получать содержимое ответа сервера в рамках кросс-доменного запроса. В случае, если ответ сервера не будет содержать заголовка Access-Control-Allow-Origin
со значением источника, откуда кросс-доменный запрос был отправлен, отправка основного запроса блокируется, или содержимое ответа не предоставляется странице.Access-Control-Allow-Credentials
— определяет, допустимы ли в рамках кросс-доменных запросов credentials
(например, cookies). Если в запросе передаются cookies пользователя, а значением Access-Control-Allow-Credentials
будет false
, отправка основного запроса блокируется, или содержимое ответа не предоставляется странице.Access-Control-Allow-Methods
— определяет, какие методы допустимы в рамках кросс-доменных запросов. В случае, если в ответе на предварительный запрос в этом заголовке не будет указан метод основного запроса, его отправка блокируется.Access-Control-Allow-Headers
— определяет, какие заголовки допустимы в рамках кросс-доменного запроса. В случае, если в основном запросе будет присутствовать заголовок, который не указан в Access-Control-Allow-Headers
, его отправка блокируется.В CORS запросы подразделяются на два типа: простые и предварительные. В зависимости от типа определяется, какие заголовки в рамках ответа сервера нужны, будет ли отправка запроса заблокирована, или странице не будет предоставлено содержимое ответа сервера.
Далее приведены простые сценарии осуществления обоих типов запросов.
Запрос считается простым, если:
GET
, HEAD
, POST
;Accept
, Accept-Language
, Content-Language
, Content-Type
, Range
;Content-Type
содержит одно из следующих значений: application/x-www-form-urlencoded
, multipart/form-data
, text/plain
;Смоделируем ситуацию, в которой мы отправляемGET
-запрос, содержащий заголовок Content-Type
со значением text/plain
. Отправляться запрос будет со страницы http://localhost:4000
на сервер, находящийся по адресу http://localhost:4001
.
Запрос будет отправлен, и ответ придёт. Статус у ответа будет успешным. Но в связи с тем, что порты у веб-страницы и у сервера разные, Same-Origin Policy они не удовлетворят. И, как следствие, сам браузер не предоставит странице доступ к содержимому ответа.
Чтобы позволить странице получить доступ к содержимому ответа, сервер должен вернуть правильный CORS-заголовок Access-Control-Allow-Origin
со значением http://localhost:4000
. В этом случае браузер предоставит нашей странице содержимое ответа.
В случае, если в запросе отправлялись какие-либо credentials
(к примеру, cookies или TLS сертификаты), а в ответе сервера не будет заголовка Access-Control-Allow-Credentials
со значением true
, браузер не предоставит странице доступ к содержимому ответа.
В случае, если отправляемый запрос не удовлетворяет какое-либо из условий простого запроса, перед его отправкой на сервер браузер отправит preflight-запрос.
К примеру, заменим в нашем запросе метод GET
на метод DELETE
. В этом случае браузер поступит иначе. Серверу перед основным запросом будет отправлен preflight-запрос с методом OPTIONS
. Он будет содержать информацию о нашем основном запросе: его метод, адрес веб-страницы, с которой он был отправлен, его заголовки.
В ответ браузер ожидает получить нужные CORS-заголовки. Однако здесь есть одно важное отличие: в случае, если ответ на preflight-запрос "не удовлетворит" браузер, основной запрос отправлен не будет.
Так же, как и в нашем предыдущем примере, мы ожидаем увидеть в ответе на preflight-запрос заголовок Access-Control-Allow-Origin
со значением http://localhost:4000
.
Помимо него важную роль играют и другие CORS-заголовки. К примеру, если заголовок Access-Control-Allow-Methods
не будет содержать значения DELETE
, основной запрос также не будет отправлен.
Важно рассказать про один фундаментальный момент в контексте CORS. Заголовок Access-Control-Allow-Origin
, помимо конкретного хоста, может принимать значение *
(wildcard). Оно разрешает хосту абсолютно любого происхождения просматривать содержимое ответа сервера. Это может быть нежелательным поведением, особенно если изначально предполагалось, что эти ресурсы должны предоставляться лишь веб-странице с определённым доменом.
То же самое касается и заголовка Access-Control-Allow-Credentials
со значением true
. С ним нужно быть очень аккуратным, особенно если значение для заголовка Access-Control-Allow-Origin
на сервере генерируется динамически, а не берётся из "белого списка". Это может открыть достаточно большое пространство для уязвимостей.
Нарушая принцип минимальных привилегий, вы рискуете подвергнуть своё веб-приложение следующим небезопасным ситуациям:
Поэтому, если приложение развёрнуто не в тестовой среде или не подразумевается, что оно представляет собой публичный API, заголовок Access-Control-Allow-Origin
должен определяться конкретным значением из "белого списка".
Если есть желание подробнее ознакомиться с возможными уязвимостями, к которым приводит неаккуратное использование CORS, ниже представлены несколько полезных статей:
Также, если есть желание глубже ознакомиться с теорией CORS, ниже предоставлены полезные ссылки:
0