2.4.3.16. Ошибки CORS и проблемы кросс-сайтовых AJAX-запросов
Причина
Важные моменты:
- Заголовок
Access-Control-Allow-Originустанавливается на сервере, откуда сайт загружает ресурсы (не на сервере с сайтом). - Заголовок должен быть только один. При дублировании браузер будет возвращать ошибку его использования.
XMLHttpRequest — это API, который используется JS-скриптами для отправки запросов к серверу. Часто используется для создания интерактивных страниц с загрузкой данных на лету без перезагрузки страницы. В целях безопасности по умолчанию можно отправлять запросы только в пределах одного домена. Это обеспечивается с помощью использования CORS, который ограничивает все кросс-сайтовые HTTP-запросы.
Адрес сайта, с которого выполнялся запрос, указывается в заголовке Origin:
GET /example/ HTTP/1.1
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
Accept: application/json, text/plain, */*
Referer: http://for.example.com/
Origin: http://for.example.com
Пример ответа сервера на такой запрос:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Date: Sat, 01 Jan 2001 00:00:00 GMT
Server: nginx
Content-Length: 35
Connection: keep-alive
Access-Control-Allow-Origin: http://for.example.com
В этом случае заголовок Access-Control-Allow-Origin разрешает запросы с указанного адреса и запрещает с других адресов. Именно из-за отсутствия такого заголовка может возникать проблема при кросс-доменных запросах. Принцип работы заголовка Access-Control-Allow-Origin состоит в том, чтобы запрещать или разрешать использовать ресурсы одного сайта в рамках других сайтов. Отсутствие заголовка Access-Control-Allow-Origin равноценно установке запрета на использование ресурсов.
Решение
Важные моменты:
- Заголовки CORS добавляется на том сервере, откуда сайт загружает ресурсы. Если ваш сайт находится на нашем хостинге и загружает ресурсы со стороннего сервера, то добавлять заголовки нужно на стороннем сервере.
- Добавление заголовков CORS на уровне PHP имеет больший приоритет, чем добавление на уровне .htaccess. При установке заголовков на уровне PHP и на уровне .htaccess будут действовать те, что установлены на уровне PHP.
- Заголовки CORS, которые добавлены с помощью PHP или .htaccess не работают для статических файлов, так как такие файлы обрабатываются веб-сервером nginx. Для таких файлов используйте настройку CORS через панель управления.
В разделе «Настройки сайта» под списком статических файлов включите «Добавлять заголовок Access-Control-Allow-Origin: * для статических файлов» и сохраните изменения:
На целевом сервере (куда сайт отправляет запросы) в PHP-скриптах загружаемых страниц добавьте такие директивы:
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With, Content-Type, Accept, Origin, Authorization');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
* означает, что разрешены запросы с любых адресов. Если нужно разрешить запросы только с конкретного адреса, укажите его вместо * в формате http://example.com (если адресов несколько, продублируйте директиву для каждого адреса).
На целевом сервере (куда сайт отправляет запросы) в файле .htaccess добавьте такие директивы:
Header add Access-Control-Allow-Origin "*"
Header add Access-Control-Allow-Headers "origin, x-requested-with, content-type"
Header add Access-Control-Allow-Methods "PUT, GET, POST, DELETE, OPTIONS"
* означает, что разрешены запросы с любых адресов. Если нужно разрешить запросы только с конкретного адреса, укажите его вместо * в формате http://example.com (если адресов несколько, продублируйте директиву для каждого адреса).