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

Почему стандартные методы не работают для нескольких доменов

Браузеры реализуют политику同源 (Same-Origin Policy). Она запрещает скрипту на одном домене читать ответ от сервера на другом. Если вы попытаетесь разрешить доступ через файл конфигурации типа .env или переменные окружения, браузер всё равно заблокирует запрос, если заголовок Origin не совпадает с тем, что указан в настройках.

Стандартный подход — указание доменов в заголовке Access-Control-Allow-Origin. Однако этот заголовок должен содержать либо конкретный домен, либо значение *. Если вы укажете несколько доменов через запятую (например, site1.com, site2.com), браузер проигнорирует это и вернет ошибку CORS.

Поэтому для нескольких фронтендов нельзя использовать один статический заголовок. Необходимо динамически формировать ответ сервера в зависимости от того, откуда пришёл запрос.

Архитектурное решение: проверка источника на сервере

Сервер должен проверять заголовок Origin каждого входящего запроса. Если он совпадает с одним из разрешённых доменов, сервер добавляет соответствующий заголовок в ответ. Если источник неизвестен или запрещён — сервер возвращает ошибку 403 или 401.

Это решение работает независимо от языка программирования бэкенда: Node.js, Python, PHP, Go и других. Логика одна: получить Origin, сравнить с списком доверенных, вернуть заголовок только если совпадение найдено.

Практическая реализация на примере Node.js

В качестве примера рассмотрим middleware для Express. Он проверяет Origin и добавляет заголовок, если домен разрешён.

Создайте массив или Set с доверенными доменами. Используйте Set для быстрого поиска совпадений.

Проверяйте только протокол (http/https) и хост, игнорируя путь и порт. Например, запрос к https://site1.com/api будет иметь Origin https://site1.com.

Если Origin совпадает с одним из доверенных, добавьте заголовок Access-Control-Allow-Origin с этим значением. Не добавляйте несколько значений в один заголовок.

Учёт протоколов и портов

При настройке учитывайте, что запросы могут приходить по http или https. Если ваш бэкенд работает только по https, разрешите только https-домены во фронтендах.

Если вы используете локальную разработку (localhost), добавьте его в список доверенных источников отдельно. В продакшене localhost обычно не нужен.

Как оценить результат настройки

Откройте консоль разработчика в браузере на одном из фронтендов.

Выполните запрос к API.

Проверьте заголовок Response Headers. Там должен быть Access-Control-Allow-Origin с вашим доменом.

Если заголовка нет или он содержит *, но запрос был сделан с другого домена — настройка некорректна.

Тестирование должно проводиться из разных браузеров и на разных устройствах, чтобы исключить специфичные проблемы.

Ограничения и риски

Не разрешайте доступ всем доменам (*.example.com). Это уязвимость. Укажите только конкретные поддомены, которым нужен доступ.

Если вы используете заголовок Access-Control-Allow-Credentials: true, то значение Origin должно быть точным совпадением. Значение * недопустимо в этом случае.

Не полагайтесь на клиентские библиотеки для фильтрации запросов. Фильтрация должна происходить на сервере.

Частые ошибки при настройке

Ошибка: Указание нескольких доменов через запятую в одном заголовке. Решение: используйте middleware, который добавляет заголовок только для текущего Origin.

Ошибка: Игнорирование протокола. Если фронтенд работает по http, а бэкенд по https, браузер заблокирует запрос как небезопасный. Используйте https везде или настройте редирект.

Ошибка: Использование заголовка Vary: Origin без проверки. Это нужно для кэширования, но не заменяет проверку самого Origin.

Интеграция в существующие системы

Если у вас уже есть работающий сервис, добавьте middleware CORS без остановки работы. Обычно это делается на уровне роутинга или глобального middleware.

Для микросервисов настройку можно централизовать в одном модуле безопасности и распространять на все сервисы через конфигурацию.

Вопросы и ответы

Можно ли использовать заголовок Access-Control-Allow-Origin: * для нескольких доменов?

Нет. Значение * разрешает доступ всем, но если вы используете заголовки с credentials (cookies), браузер заблокирует запрос. Кроме того, это небезопасно для публичных API.

Как добавить локальный домен localhost в список разрешённых?

Добавьте 'http://localhost' и 'http://localhost:3000' (или ваш порт) в список доверенных источников. В продакшене их обычно не нужно.

Что делать, если запросы идут с разных поддоменов одного домена?

Добавьте каждый поддомен (например, app.site.com и mobile.site.com) в список разрешённых. Браузер считает их разными источниками.

По теме

// Пример middleware для Express
const allowedOrigins = new Set(['https://site1.com', 'https://site2.com']);

function corsMiddleware(req, res, next) {
  const origin = req.headers.origin;
  if (allowedOrigins.has(origin)) {
    res.setHeader('Access-Control-Allow-Origin', origin);
  }
  next();
}

app.use(corsMiddleware);