php

Ошибка “… blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested …”

Ошибка blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present — одна из самых частых проблем при разработке веб-приложений, работающих с внешними API или несколькими доменами. В этой статье разберём, что такое CORS, почему браузер блокирует такие запросы и как правильно настроить заголовки на стороне сервера.

Что такое CORS и почему браузер блокирует запросы

CORS (Cross-Origin Resource Sharing) — механизм безопасности браузера, основанный на HTTP-заголовках. Он ограничивает JavaScript-код на одном домене от обращения к ресурсам другого домена. Это называется политикой одного источника (Same-Origin Policy).

Браузер считает запрос кросс-доменным, если отличается хотя бы один из трёх параметров: протокол, домен или порт. Например, запрос с https://example.com к https://api.other.com — кросс-доменный. Если сервер не сообщает браузеру явно, что разрешает такие запросы, браузер блокирует ответ и выбрасывает ошибку CORS.

Важно понимать: блокировка происходит на стороне браузера, а не сервера. Сервер получает запрос и возвращает ответ, но браузер отказывается передавать этот ответ JavaScript-коду, если в ответе нет нужных заголовков.

Когда возникает эта ошибка

Ошибка появляется при AJAX-запросах (fetch, XMLHttpRequest) к ресурсам на другом домене или поддомене. Типичные сценарии:

  • Фронтенд на localhost:3000 обращается к API на localhost:8080
  • Сайт на shop.example.com делает запрос к api.example.com
  • Веб-приложение обращается к стороннему REST API без CORS-поддержки
  • Мобильное веб-приложение запрашивает данные с отдельного бэкенд-сервера

Решение 1: Заголовок в PHP

Самый простой способ — добавить заголовок в PHP-коде. Символ * означает разрешение запросов с любого домена:

Однако в большинстве случаев лучше указывать конкретный домен. Это безопаснее, так как ограничивает круг разрешённых источников:

Если нужно разрешить запросы с нескольких доменов, реализуйте динамическую проверку:

Решение 2: Настройка через .htaccess (Apache)

Для Apache добавьте в файл .htaccess следующие директивы:

Если модуль mod_headers не включён, выполните: a2enmod headers и перезапустите Apache.

Решение 3: Настройка в nginx

В конфигурации nginx добавьте в блок location или server:

Решение 4: Для Битрикс — где добавить заголовки

В 1С-Битрикс заголовки удобнее всего добавлять в файл /bitrix/php_interface/init.php. Это гарантирует, что заголовки будут установлены при каждом запросе:

Обработка preflight OPTIONS-запросов

Браузер перед «сложным» запросом (с нестандартными заголовками или методами PUT/DELETE) автоматически отправляет preflight-запрос методом OPTIONS. Сервер должен корректно на него ответить, иначе основной запрос не выполнится. Добавьте обработчик:

Безопасность: почему не стоит всегда использовать *

Символ * удобен для публичных API, но опасен там, где используется авторизация. При Access-Control-Allow-Origin: * нельзя одновременно использовать Access-Control-Allow-Credentials: true — браузер выдаст ошибку. Кроме того, открытый CORS позволяет любому сайту читать ответы вашего API от имени авторизованного пользователя.

Для API с авторизацией всегда указывайте конкретный домен и добавляйте заголовок Vary: Origin, чтобы кэш корректно обрабатывал разные источники:

Правильная настройка CORS позволяет строить безопасные кросс-доменные интеграции без риска для данных пользователей.