2.20.16. Ошибки CORS и проблемы кросс-сайтовых AJAX-запросов
Важные моменты:
- Заголовок
Access-Control-Allow-Origin
устанавливается на сервере, где размещается запрашиваемый сайтом ресурс. - Заголовок
Access-Control-Allow-Origin
должен возвращаться только один. При дублировании заголовка браузер будет возвращать ошибку его использования.
XMLHttpRequest — это API, который используется JS-скриптами для отправки запросов к серверу. Довольно часто он используется для создания интерактивных страниц с загрузкой данных на лету без перезагрузки страницы. Использование такого API довольно популярно, но в целях безопасности по умолчанию можно отправлять запросы только в рамках одного домена. Такая безопасность организована благодаря использованию 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
равноценно тому же, что и указание запрета на использование ресурсов.
Решить проблему можно несколькими способами:
Важные моменты:
- Добавление заголовков с помощью PHP приоритетнее, чем настройка через .htaccess. В таком случае, если в рамках сайта в PHP-скриптах настроена определённая политика CORS, указание других данных через .htaccess не изменит заголовки.
- Способы реализации передачи заголовков CORS с помощью PHP и через .htaccess не будут работать для статических файлов, так как их обработка производится веб-сервером nginx. Чтобы установить настройки политики CORS для статических файлов, нужно воспользоваться первым способом.
- Для статических файлов можно установить параметр в настройках сайта, который будет указывать на разрешение доступа с любого адреса (обратите внимание: данный способ не действует на файлы, которые не указаны в списке статических):
- В 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"
Для разрешения доступа нескольким адресам их нужно указать с новой строки, к примеру так:
Header add Access-Control-Allow-Origin "http://some.for.example.com" Header add Access-Control-Allow-Origin "http://for.example.com" Header add Access-Control-Allow-Origin "http://example.com"