Классическая ситуация в проектах на Nginx как обратном прокси: заголовок Access-Control-Allow-Origin уже прописан в самом бэкенде (Laravel, Express, Django — неважно), но администратор дополнительно добавляет add_header Access-Control-Allow-Origin *; в конфиг Nginx "на всякий случай". В результате браузер получает два значения заголовка через запятую и отклоняет ответ целиком — CORS-заголовок обязан быть ровно одним значением, а не списком.
Политика единого источника
По умолчанию браузеры действуют по Same-Origin Policy: JavaScript-код со страницы одного источника (домен + протокол + порт) не может читать ответы от запросов к другому источнику. Это фундаментальный защитный механизм, не позволяющий вредоносному скрипту на одном сайте красть данные с другого сайта, где пользователь авторизован.
Как CORS ослабляет эту политику
CORS (Cross-Origin Resource Sharing) — это набор HTTP-заголовков, которыми сервер явно разрешает определённым (или всем) внешним источникам читать свои ответы. Ключевой заголовок — Access-Control-Allow-Origin, указывающий, какие домены имеют разрешение.
Ловушка wildcard-источника с credentials
Если фронтенд отправляет запрос с credentials: 'include' (например, чтобы передать cookie сессии на поддомен API), браузер категорически отказывается принимать в ответ Access-Control-Allow-Origin: * — спецификация прямо запрещает сочетание wildcard-источника с credentials, сервер обязан вернуть точный домен запросившего источника.
Зачем это нужно
- Диагностировать CORS-ошибку и понять, каких именно заголовков не хватает на сервере.
- Найти дублирующиеся CORS-заголовки при связке Nginx + бэкенд-фреймворк.
- Понять разницу между "простыми" запросами и preflight-запросами (OPTIONS).
CORS не защищает сервер от атак
CORS — это механизм, ограничивающий только браузер и только JavaScript-код на веб-странице; он никак не мешает злоумышленнику отправить тот же запрос напрямую через curl, Postman или собственный скрипт на бэкенде, минуя браузер полностью. Поэтому CORS никогда нельзя рассматривать как замену настоящей авторизации на сервере — это инструмент управления тем, какие сайты могут использовать API из браузера пользователя, а не барьер против атак в целом.