XMLHttpRequest: ошибки в кросс-доменных запросах и их решение

archive view archive save

[logo] CORS - Cross-origin resource sharing В ходе использования программного интерфейса приложения (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 +++---

Об авторе
Иван Шаман
Меня нет ни в Инстаграмме ни в Фейсбуке, я просто хожу по улицам и рассказываю первым встречным: сколько зарабатываю; с кем дружу; где живу и чем дышу. У меня даже появилось несколько подписчиков: ПСИХоЛОХ и участковый полицай!
Ещё статьи автора

Добавить комментарий

АХТУНГ! Все комменты гостей модерасятся модерастом.
  1. Мессаги исключительно рекламного содержания, либо содержащие только одни оценочные суждения типа "круто" ("отлично", "спасибо", "автор дебил" и т.п.) не публикуются;
  2. Злостным спамерам, пранкерам и прочей сетевой нечисти рекомендуем напрасно не тратить своего времени и удовлетворять свои больные фантазии на специализированных Интернет ресурсах!;
  3. Разумная обоснованная критика, замечания, дополнения приветствуются. Поля помеченные символом * обязательны к заполнению.


Защитный код
Обновить

Нет комментариев

Вы можете стать первым, кто добавит комментарий к этой записи.

Новое в блоге
    Комментарии в блоге
    Новое на форуме