Поиск по сайту:

Обработка CORS в веб-приложениях


CORS — это механизм браузера, который позволяет серверам указывать сторонние источники, которые могут запрашивать у них ресурсы. Это защита безопасности, которая помогает предотвратить кражу вредоносными сайтами данных, принадлежащих другим источникам.

CORS расшифровывается как Cross-Origin Resource Sharing. Когда CORS используется для загрузки ресурса, браузер обычно отправляет предварительный HTTP-запрос OPTIONS. Сервер должен ответить, указав источники, с которыми он будет взаимодействовать. Он также может определять дополнительные ограничения, такие как заголовки HTTP, которые могут быть отправлены.

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

Когда используется CORS

Браузеры применяют CORS для запросов Ajax и Fetch. Этот механизм также будет использоваться для веб-шрифтов, текстур WebGL и отрисовки изображений холста с помощью drawImage(). Для любого приемлемого запроса к стороннему источнику потребуется обмен CORS.

CORS не будет применяться, если запрос рассматривается как «простой». Простой запрос должен быть GET, HEAD или POST с типом содержимого text/plain, application/x-www-form-urlencoded или multipart/form-data. Единственными допустимыми простыми заголовками запроса являются Accept, Accept-Language, Content-Language и Content-Type.

Если запрос не соответствует всем вышеперечисленным критериям, обмен CORS будет запущен современными браузерами. Важно понимать, что CORS — это технология, основанная на браузере. Вы никогда не столкнетесь с CORS при выполнении запросов вручную, например, с помощью curl в своем терминале.

Обмены CORS не всегда отправляют предварительный запрос OPTIONS. Предварительная проверка используется, когда запрос вызовет «побочные эффекты» на сервере. Обычно это относится к методам запроса, отличным от GET.

Представьте запрос POST в /api/users/create. Сервер всегда будет создавать нового пользователя, но браузер может отказать в доступе к ответу, если запрос подвергался CORS. Если сначала отправить запрос OPTIONS, сервер может явно отклонить настоящий запрос. Это гарантирует, что учетная запись пользователя фактически не создается.

Обработка CORS на стороне клиента

Хотя CORS — это технология браузера, вы не можете напрямую влиять на нее с помощью кода на стороне клиента. Это не позволяет вредоносным сценариям обходить защиту CORS для загрузки данных из сторонних доменов.

CORS обычно прозрачен, поэтому вы не будете знать, что он работает. Если обмен CORS не удастся, ваш код JavaScript увидит общую сетевую ошибку. Невозможно получить точную информацию о том, что пошло не так, так как это может представлять угрозу безопасности. Полная информация записывается в консоль.

Единственный способ устранить сбой CORS — убедиться, что ваш сервер отправляет правильные заголовки ответа. Давайте теперь посмотрим, как это делается.

Обработка CORS на стороне сервера

Сначала вы должны убедиться, что ваш сервер правильно обрабатывает запросы OPTIONS. Возможно, вам потребуется создать новый маршрут в вашей веб-инфраструктуре. Как правило, вам необходимо принимать запросы OPTIONS к каждой конечной точке, которая может получить запрос от браузера из разных источников. У ответа не обязательно должно быть тело, но он должен включать определенные заголовки, которые информируют браузер о дальнейших действиях.

Начните с добавления заголовка Access-Control-Allow-Origin. Это указывает сторонний источник, которому разрешено взаимодействовать с вашей конечной точкой. Можно указать только одно происхождение; вы можете обрабатывать несколько источников, динамически устанавливая значение заголовка для источника, из которого был отправлен запрос. Вы можете получить текущий источник из заголовка запроса Origin.

Access-Control-Allow-Origin принимает * в качестве специального значения подстановочного знака. Это разрешит запросы CORS из всех источников. Будьте осторожны при использовании этого — указание разрешенных источников дает вам больше контроля и не позволяет вредоносным скриптам запрашивать данные с вашего сервера.

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

Указание перекрестных заголовков

Запросы CORS обычно поддерживают только «простые» заголовки запросов, перечисленные выше. Если вам нужно использовать какой-либо другой заголовок, например Авторизация или пользовательский заголовок, ваш сервер должен будет явно разрешить это в ответе предварительной проверки.

Установите заголовок Access-Control-Allow-Headers. Его значение должно быть списком имен заголовков, разделенных запятыми, которые будут приняты с реальным запросом.

Access-Control-Allow-Headers: Authorization, X-Custom-Header

Браузер теперь будет разрешать продолжение запроса с заголовками Authorization или X-Custom-Header.

Когда браузер отправляет предварительный запрос CORS, он отправляет заголовок Access-Control-Request-Headers. Он содержит список заголовков, которые будут отправлены с фактическим запросом. Ваш серверный код может использовать эту информацию при определении того, как отвечать на предварительный запрос.

Ограничение конкретными методами запроса

Аналогично указанию заголовков запроса, конечные точки сервера могут определять, какие методы HTTP должны быть разрешены из разных источников. Установите заголовок Access-Control-Allow-Methods в виде списка имен методов, разделенных запятыми.

Access-Control-Allow-Methods: GET, POST, DELETE

Браузер отправляет заголовок Access-Control-Request-Method с предварительными проверками CORS. Это позволяет вашему серверу узнать метод HTTP, который будет использоваться для выполнения окончательного запроса.

Файлы cookie и учетные данные

Запросы CORS обычно не отправляют файлы cookie, поскольку они могут содержать конфиденциальные учетные данные, идентифицирующие отправителя. Если вам нужно включить файлы cookie с запросом на другой источник, вы должны явно включить это в коде на стороне клиента:

fetch("https://localhost/demo", {
    mode: "cors",
    credentials: "include"
});

Кроме того, сервер должен установить заголовок ответа Access-Control-Allow-Credentials: true, чтобы сообщить о своем согласии на обмен файлами cookie с учетными данными.

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

Предполетное кэширование

Предварительные проверки CORS OPTIONS добавляют дополнительную нагрузку на каждый сделанный вами запрос. Хотя задержка должна быть едва заметной при хорошем сетевом соединении, тем не менее, это расточительно, когда вы вызываете одну и ту же конечную точку несколько раз в быстрой последовательности.

Вы можете указать браузеру кэшировать предварительные ответы, установив заголовок Access-Control-Max-Age. Значение должно быть временем в секундах, в течение которого браузеру разрешено кэшировать ответ. Последующие запросы к той же конечной точке в течение заданного периода не будут отправлять предварительную проверку CORS.

Заключение

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

Фактическая реализация CORS довольно проста. Убедитесь, что ваш API или CDN отправляет правильные заголовки ответов, в первую очередь Access-Control-Allow-Origin. После этого у вас будет безопасная связь между источниками, которая поможет защититься от злоумышленников.