HTTPQUERY
Русский

Access-Control-Allow-Origin

Применение

Примечание

CORS (Cross-Origin Resource Sharing, совместное использование ресурсов между источниками) — это браузерный механизм, который запрещает веб-страницам читать ответы, отданные другим источником, если сервер явно не разрешил доступ. Браузеры автоматически устанавливают заголовок Origin в кросс-доменных запросах. JavaScript не может изменить заголовок Origin.

Каждый ответ CORS содержит Access-Control-Allow-Origin, чтобы сообщить браузеру, разрешено ли клиентскому коду с конкретного источника читать ответ. Без совпадающего значения браузер не пропустит ответ к JavaScript.

У сервера, решившего разрешить доступ, есть три варианта: подстановочный знак, явный источник или null. Большинство production-API выбирают источник динамически, сравнивая входящий заголовок запроса Origin со списком разрешённых значений. При совпадении сервер возвращает это значение обратно. Поскольку ответ меняется в зависимости от запроса, требуется заголовок Vary: Origin, чтобы кэши хранили отдельные копии для каждого источника.

Что запускает CORS

Любой fetch() или XMLHttpRequest к другому источнику запускает проверку CORS. Загрузка шрифтов через @font-face, текстуры WebGL и canvas.drawImage() с кросс-доменными изображениями также приводят к проверкам CORS. Запросы с пользовательскими заголовками, с непростыми методами вроде PUT, DELETE или PATCH, либо с Content-Type вида application/json вызывают предварительный запрос OPTIONS перед отправкой самого запроса. Обычная навигация — переход по ссылкам или загрузка страниц в браузере — CORS не запускает.

* (подстановочный знак)

Разрешает любому источнику читать ответ. Подстановочный знак действителен только для запросов без учётных данных.

Access-Control-Allow-Origin: *

Примечание

Подстановочный знак несовместим с запросами, передающими учётные данные. Когда Access-Control-Allow-Credentials равен true, сервер обязан вернуть явный источник.

Явный источник

Одно значение источника, состоящее из схемы, имени хоста и необязательного порта. Это стандартный подход для API, ограниченных известными вызывающими сторонами.

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

В одном ответе допускается только один источник. Серверы, поддерживающие несколько источников, проверяют заголовок запроса Origin и отвечают совпавшим значением, добавляя в ответ Vary: Origin.

null

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

Access-Control-Allow-Origin: null

Примечание

Отвечать значением null не рекомендуется. Вредоносные документы из iframe в песочнице тоже несут источник null, поэтому это значение легко подделать.

Пример

Сервер динамически отражает источник запроса и включает заголовок Vary для корректного поведения кэша.

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

Публичный CDN, отдающий статические ресурсы любому вызывающему, использует подстановочный знак.

Access-Control-Allow-Origin: *

Кросс-доменный ответ с учётными данными сочетает явный источник с заголовком учётных данных.

Access-Control-Allow-Origin: https://dashboard.example.re
Access-Control-Allow-Credentials: true
Vary: Origin

Диагностика

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

В консоли выводится “No ‘Access-Control-Allow-Origin’ header is present on the requested resource.”. Сервер вообще не включил этот заголовок. Убедитесь, что серверная конфигурация CORS применяется к конкретному маршруту и HTTP-методу. В nginx проверьте, что директива add_header находится внутри нужного блока location. В Apache проверьте, что Header set находится внутри соответствующего или . Протестируйте с помощью curl, чтобы отделить проблему от поведения браузера: curl -v -H “Origin: https://example.com” https://api.example.re/data

Подстановочный знак * не работает с запросами, передающими учётные данные. Браузеры отклоняют ответы, в которых Access-Control-Allow-Origin: * сочетается с Access-Control-Allow-Credentials: true. Решение — прочитать входящий заголовок Origin, проверить значение по списку разрешённых и вернуть совпавший источник обратно. Добавьте в ответ Vary: Origin, чтобы кэши хранили отдельные копии для каждого источника.

Отражение источника без проверки. Дословное возвращение заголовка запроса Origin без сверки со списком разрешённых открывает API для любого домена. Злоумышленники используют это, чтобы похищать данные через подконтрольную им страницу. Всегда сравнивайте входящий источник со списком доверенных значений, прежде чем отражать его.

CDN кэширует ответ с неверным источником. Когда сервер возвращает динамическое значение источника, но опускает Vary: Origin, CDN сохраняет первое значение источника и отдаёт один и тот же кэшированный ответ каждому последующему источнику. Добавляйте Vary: Origin в каждый ответ, отражающий динамический источник. В Cloudflare это обрабатывается автоматически при использовании управляемого преобразования CORS. В других CDN убедитесь, что источник входит в ключ кэширования.

Предварительный запрос проходит, а фактический запрос завершается неудачей. Ответ на OPTIONS содержит заголовки CORS, а последующий ответ на GET, POST или PUT — нет. Многие серверные фреймворки обрабатывают OPTIONS отдельно от остальных методов. Убедитесь, что заголовки CORS добавляются ко всем типам ответов, а не только к ответам на предварительные запросы. В Express разместите промежуточное ПО CORS перед обработчиками маршрутов, чтобы каждый ответ проходил через него.

Отладка с помощью curl показывает корректные заголовки, но браузер по-прежнему блокирует запрос. Откройте DevTools, перейдите на вкладку Network и изучите фактические заголовки ответа, полученные браузером. Прокси, балансировщики нагрузки или пограничные правила CDN иногда удаляют или перезаписывают заголовки CORS между сервером-источником и браузером. Сравните вывод curl с выводом DevTools, чтобы найти слой, удаляющий заголовок.