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: *
Риски
-
Access-Control-Allow-Origin: *с авторизацией Если сервер разрешает всем доступ и одновременно присылает cookie или токен — это уязвимость. -
Отсутствие контроля Если сервер без разбора разрешает всем (например,
Access-Control-Allow-Origin: *), злоумышленники могут использовать твой API в своих целях. -
Ошибки при разработке Часто блокируются запросы между
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);
}