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 (якщо адрес кілька, продублюйте директиву для кожної адреси).

Не впливає на статичні файли і не перевизначає заголовки CORS, які додані на рівні PHP.

На цільовому сервері (куди сайт надсилає запити) у файлі .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 (якщо адрес кілька, продублюйте директиву для кожної адреси).

Зміст

    (2)