В ходе использования программного интерфейса приложения (API) XMLHttpRequest скриптового языка браузеров JavaScript, обычно в тандеме с технологией AJAX (Asynchronous JavaScript And XML), могут возникать различные ошибки CORS (Cross-origin resource sharing) при попытке доступа к ресурсам другого домена.
Здесь мы условились о том, что:
- src.example.org - это домен, с которого отправляются XMLHttpRequest кросс-доменные запросы
- target.example.com/example.php - это домен и скрипт /example.php, на который XMLHttpRequest кросс-доменные запросы отправляются
Перечисленные ниже CORS ошибки приводятся в том виде, в котором они выдавались в консоль веб-браузера.
https://target.example.com/example.php в данном примере фактически был размещён на сервере страны отличной от Украины и посредством CURL предоставлял доступ к российскому сервису проверки правописания от Яндекса, - как извесно доступ к сервисам Яндекса из Украины был заблокирован большинством Интернет-провайдеров.
При попытке проверить правописание в редакторе выдавалась ошибка: "The spelling service was not found: (https://target.example.com/example.php)"
Причина: отсутствует заголовок CORS 'Access-Control-Allow-Origin'
"NetworkError: 403 Forbidden - https://target.example.com/example.php"
example.php
Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на https://target.example.com/example.php. (Причина: отсутствует заголовок CORS 'Access-Control-Allow-Origin').
Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на https://target.example.com/example.php. (Причина: не удалось выполнить запрос CORS).
Решение: отсутствует заголовок CORS 'Access-Control-Allow-Origin'
CORS для src.example.org должно быть разрешено на стороне сервера принимающего запросы - это можно сделать в .htaccess следующим образом:
<Files ~ "(example)+\.php"> Header set Access-Control-Allow-Origin "https://src.example.org" </Files>
Причина: неудача канала CORS preflight
"NetworkError: 403 Forbidden - https://target.example.com/example.php" example.php
Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на https://target.example.com/example.php. (Причина: неудача канала CORS preflight).
Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на https://target.example.com/example.php. (Причина: не удалось выполнить запрос CORS).
Решение: неудача канала CORS preflight
Причины здесь могут быть разные, среди которых может быть запрет некоторых ИП на стороне брандмауэра, либо ограничения на методы запроса в том же .htaccess строкой: "RewriteCond %{REQUEST_METHOD} !^(post|get) [NC,OR]".
Во-втором случае это может быть зафиксировано в лог-файле ошибок сервера:
xxx.xxx.xx.xxx [07/May/2018:09:55:15 +0300] "OPTIONS /example.php HTTP/1.1" 403 "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:52.0) Gecko/20100101 Firefox/52.0" "Referer: -"
Примечание:
Нужно помнить, что ИП-адрес в лог-файле сервера принадлежит клиенту/браузеру, а не удалённому серверу src.example.org на страницах которого в браузере клиента был инициирован CORS (кросс-доменный) запрос!
В случае с .htaccess строку подправим до такого состояния: "RewriteCond %{REQUEST_METHOD} !^(post|get|options) [NC,OR]".
Причина: отсутствует токен 'x-requested-with' в заголовке CORS 'Access-Control-Allow-Headers' из канала CORS preflight
Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на https://target.example.com/example.php. (Причина: отсутствует токен 'x-requested-with' в заголовке CORS 'Access-Control-Allow-Headers' из канала CORS preflight).
Запрос из постороннего источника заблокирован: Политика одного источника запрещает чтение удаленного ресурса на https://target.example.com/example.php. (Причина: не удалось выполнить запрос CORS).
Решение: отсутствует токен 'x-requested-with' в заголовке CORS 'Access-Control-Allow-Headers' из канала CORS preflight
Посредством .htaccess добавим заголовок Access-Control-Allow-Headers:
<Files ~ "(example)+\.php"> Header set Access-Control-Allow-Origin "https://src.example.org" Header set Access-Control-Allow-Headers: "X-Requested-With" </Files>
Access-Control-Allow-Origin для множества доменов
Заголовок Access-Control-Allow-Origin допускает установку только одного источника, однако при необходимости разрешения CORS для множества источников в .htaccess можно извратится следующим образом:
##### ---+++ BEGIN MOD HEADERS CONFIG +++--- <IfModule mod_headers.c> <Files ~ "(example)+\.php"> #Header set crossDomain: true # ## Allow CORS from one domain #Header set Access-Control-Allow-Origin "https://src.example.org" ## Allow CORS from multiple domain SetEnvIf Origin "http(s)?://(www\.)?(example.org|src.example.org)$" AccessControlAllowOrigin=$0 Header set Access-Control-Allow-Origin %{AccessControlAllowOrigin}e env=AccessControlAllowOrigin # ## Origin, X-Requested-With, Content-Type, Accept, X-Auth-Token Header set Access-Control-Allow-Headers: "X-Requested-With" # ## "GET, POST" Header set Access-Control-Allow-Methods "POST" # #Header set Access-Control-Allow-Credentials true #Header set Access-Control-Max-Age 60 </Files> </IfModule> ##### ---+++// END MOD HEADERS CONFIG +++---

