CORS (Cross-Origin Resource Sharing) — это механизм, который позволяет веб-браузерам ограничивать доступ к ресурсам, расположенным на других доменах. Этот механизм играет важную роль в обеспечении безопасности при взаимодействии с удалёнными API и другими сервисами, работающими в сети.
Когда веб-страница на одном домене (например,
example.com) пытается выполнить запрос к серверу на другом
домене (например, api.example.org), браузер по умолчанию
блокирует такой запрос из-за политики однообразного происхождения
(Same-Origin Policy). Эта политика предназначена для защиты пользователя
от потенциально опасных веб-страниц, которые могут попытаться получить
доступ к данным другого сайта без разрешения.
Однако в некоторых случаях необходимо разрешить такие кросс-доменные запросы, например, при интеграции с внешними API. В таких случаях на помощь приходит механизм CORS, который позволяет серверу явно указать, что его ресурсы доступны для запросов с других доменов.
Когда браузер пытается выполнить кросс-доменный запрос, он сначала
отправляет предварительный запрос типа OPTIONS на целевой
сервер. Этот запрос называется “preflight”. В ответ на него сервер
должен отправить заголовки, которые указывают, разрешает ли он такие
запросы с конкретного домена. Например, сервер может отправить
заголовок:
Access-Control-Allow-Origin: https://example.com
Этот заголовок позволяет домену example.com отправлять
запросы на сервер. Если сервер не отправит соответствующие заголовки,
браузер заблокирует запрос.
fetch — это стандартный API в JavaScript для выполнения
HTTP-запросов. Он поддерживает CORS из коробки, и его поведение зависит
от того, как настроены заголовки на сервере.
Когда вызывается метод fetch для выполнения
кросс-доменного запроса, браузер автоматически проверяет заголовки
ответа на соответствие политике CORS. Если запрос был выполнен корректно
и сервер разрешает доступ, данные будут доступны для обработки в
JavaScript.
Пример простого кросс-доменного запроса с использованием
fetch:
fetch('https://api.example.org/data', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
mode: 'cors' // Указывает, что запрос должен использовать CORS
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
В этом примере:
Основная опция для настройки CORS в fetch — это
mode. Этот параметр может принимать следующие
значения:
Пример использования no-cors:
fetch('https://api.example.org/data', {
method: 'GET',
mode: 'no-cors'
})
.then(response => {
console.log('Request was successful, but cannot access response data due to CORS policy.');
})
.catch(error => console.error('Error:', error));
В этом случае ответ от сервера будет недоступен в JavaScript, даже если запрос был успешным. Это часто используется для выполнения одноразовых запросов, например, при отправке данных на сервер для анализа.
В случае, если сервер не поддерживает CORS, или если заголовки ответа
не соответствуют ожиданиям браузера, запрос будет заблокирован, и это
приведёт к ошибке, которую можно обработать через
.catch().
Пример обработки ошибки CORS:
fetch('https://api.example.org/data', {
method: 'GET',
mode: 'cors'
})
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('CORS error or other:', error));
Если сервер не разрешает кросс-доменные запросы, ошибка будет выброшена, и будет выведено сообщение о том, что запрос не удался.
Если сервер не поддерживает CORS, то единственный способ разрешить доступ — это настройка правильных заголовков на серверной стороне. Основной заголовок для разрешения CORS — Access-Control-Allow-Origin.
Пример серверной настройки для разрешения CORS на домене
example.com:
Access-Control-Allow-Origin: https://example.com
Для разрешения всех доменов можно использовать:
Access-Control-Allow-Origin: *
Однако использование * может быть небезопасным, особенно
если сервер работает с чувствительными данными, так как позволяет любому
сайту обращаться к его API.
Сервер может также настроить дополнительные заголовки, такие как
Access-Control-Allow-Methods для указания разрешённых
HTTP-методов (например, GET, POST,
PUT), а также Access-Control-Allow-Headers
для разрешения определённых заголовков.
Пример разрешения методов и заголовков:
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: Content-Type
Правильная настройка CORS критична для обеспечения безопасности
веб-приложений. Разрешение запросов с произвольных доменов может
привести к утечке данных, если сервер не настроен должным образом. При
использовании * для
Access-Control-Allow-Origin стоит быть осторожным, так
как это открывает доступ к данным всем источникам, что может быть опасно
для защищённых данных.
Кроме того, для некоторых типов запросов, например, с методами
PUT или DELETE, или при использовании
нестандартных заголовков, браузер будет посылать предварительный запрос
OPTIONS. Сервер должен корректно обрабатывать такие
запросы, чтобы избежать блокировки.
Таким образом, взаимодействие с кросс-доменными ресурсами требует как настройки серверных заголовков, так и грамотной работы с API на стороне клиента.