Skip to main content

CORS (Cross-Origin Resource Sharing)

CORS — это механизм безопасности в браузерах. Он ограничивает доступ JavaScript-кода на одной странице к ресурсам с другого сайта.


Пример

Ты открыл сайт https://example.com Он хочет отправить запрос на https://api.other-site.com.

Браузер спрашивает:

other-site.com разрешал сайту example.com к себе обращаться?"

Если да — запрос проходит. Если нет — браузер блокирует его с ошибкой CORS.


Для чего это нужно

Чтобы защититься от вредоносных сайтов, которые:

  • автоматически делают запросы к API от твоего имени;
  • воруют данные с приватных сервисов, если ты авторизован.

Например, ты вошёл в свой банк. А вредоносный сайт (в другой вкладке) пытается сделать fetch('https://bank.com/api/transfer'). Браузер не позволит — сработает CORS-защита.


Как сервер сообщает, что доступ разрешён

Сервер добавляет заголовок:

Access-Control-Allow-Origin: https://example.com

или, для всех:

Access-Control-Allow-Origin: *

Риски

  1. Access-Control-Allow-Origin: * с авторизацией Если сервер разрешает всем доступ и одновременно присылает cookie или токен — это уязвимость.

  2. Отсутствие контроля Если сервер без разбора разрешает всем (например, Access-Control-Allow-Origin: *), злоумышленники могут использовать твой API в своих целях.

  3. Ошибки при разработке Часто блокируются запросы между localhost:3000 и localhost:8000, если сервер не настроен правильно.


Как разработчики это решают

  • Настраивают заголовки на бэкенде (Flask, FastAPI, Express, Nginx и т.д.);
  • Во время разработки используют прокси (vite, webpack, create-react-app);
  • В продакшене разрешают запросы только с доверенных доменов.

когда Access-Control-Allow-Origin: * безопасен, а когда — категорически нет.


Когда * (звёздочка) безопасна

Звёздочка означает:

«Разрешаю доступ любому сайту к этому ресурсу, только если запрос не содержит авторизации

Безопасно использовать *, если:

  • API публичный, ничего не требует (например, GET /weather);
  • запросы не используют cookie, Authorization, X-Token и т.д.;
  • это статический ресурс, например, изображения, CSS или JS;
  • вы специально делаете сервис общедоступным (CDN, открытые OpenAPI и т.д.).

Пример:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET

Это абсолютно нормально для публичного API или статики.


Когда * опасна

Когда запросы:

  • требуют авторизации (cookie, токены);
  • обрабатывают личные или платёжные данные;
  • меняют что-то на сервере (POST, PUT, DELETE и т.п.);
  • выполняются от лица аутентифицированного пользователя.

Пример ошибки:

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

Это запрещено по спецификации! Браузер вообще проигнорирует такой ответ. Но если это получится обойти — вы откроете свой API всем сайтам в интернете, включая злоумышленников.


Правило

Тип запросаМожно *?Почему
Публичный GETНет чувствительных данных
Статические файлыНет авторизации
Авторизованные GETДоступ только по сессии
POST с токеномРиск утечки, CSRF, CORS-bypass
Админ-панель APIНикогда нельзя *

Безопасная альтернатива

Укажи только нужные домены:

Access-Control-Allow-Origin: https://myfrontend.com

или на сервере:

if (req.origin === 'https://myfrontend.com') {
res.setHeader('Access-Control-Allow-Origin', req.origin);
}