Php разрешить кроссдоменные запросы

Кросс-доменный XMLHttpRequest

Важной составляющей технологии AJAX является XMLHttpRequest. Этот объект дает возможность осуществлять HTTP-запросы к серверу без необходимости в перезагрузке страницы.

Обычно работа с XMLHttpRequest происходит следующим образом:
1. Создание экземпляра объекта XMLHttpRequest
2. Установка обработчика события, которое происходит при изменении состояния объекта (onreadystatechange)
3. Открытие соединения (open) и отправка запроса (send)

К сожалению XMLHttpRequest работает только с теми файлами, которые находятся в том же домене, что и использующая XMLHttpRequest страница. То есть запрос можно сделать только на адреса с тем же доменом, протоколом и портом, что и текущая страница. Это сделано в целях безопасности и создает проблемы, если надо получить данные/контент с другого сайта.

Недавно передо мной возникла данная проблема, было выбрано очень простое решение, речь о котором пойдет дальше.

Проксирование! Простой и наглядный метод для осуществления кросс-доменных запросов. Суть метода такова:

1. XMLHttpRequest обращается к PHP скрипту, на своем домене, передавая ему метод запроса, адрес и параметры
2. PHP скрипт, в свою очередь, выступает в роли прокси. То есть он осуществляет запрос исходя из переданных ему параметров и возвращает ответ другого сервера JS скрипту

Работа PHP скрипта, который являет собой прокси для кросс-доменного запроса, основана на CURL.

Вот собственно сам скрипт proxy.php:
header(«Content-Type: text/xml; charset=windows-1251»);
// параметры запроса
$method = (empty($_GET[‘method’])) ? 1 : $_GET[‘method’];
$url = $_GET[‘url’];
$url = (empty($_GET[‘url’])) ? die(«no url») : $_GET[‘url’];
$params = $_GET[‘params’];
// проверим целевой домен запроса
$allowed = array(1 => «~http:\/\/(www\.)?habrahabr\.ru\/~», 2 => «~http:\/\/(www\.)?el\-egoisto\.com\/~»);
$count = count($allowed);
for ($i = 1; $i if (preg_match($allowed[$i],$url))
// домен в списке разрешенных — отправляем запрос
$ch = curl_init();
switch ($method)
case 1:
// GET запрос
curl_setopt($ch, CURLOPT_URL, $url.»?».$params);
break;
case 2:
// POST запрос
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
break;
>
curl_setopt($ch, CURLOPT_HEADER, 0);
$response = curl_exec($ch);
$header_size = curl_getinfo($ch,CURLINFO_HEADER_SIZE);
$xml = substr($response,$header_size);
echo $xml;
curl_close($ch);
exit();
>
>
?>

XMLHttpRequest обращается к нему и передает 3 параметра:
1. method – 1 для GET запроса и 2 для POST
2. url – адрес запроса
3. params – параметры запроса

PHP скрипт проверяет наличие входных параметров, проверяет разрешено ли отправлять запрос на url (массив регэкспов $allowed) и собственно отправляет запрос и возвращает ответ удаленного сервера.

Из JS этот PHP скрипт используется так:

Есть 2 функции для работы с XMLHttpRequest — CreateReq и GetData. Первая – создает экземпляр объекта, а вторая – устанавливает обработчик и отправляет запрос.
function CreateReq()
var req = null;
if (window.XMLHttpRequest)
try
req = new XMLHttpRequest();
>
catch(e)
req = null;
>
>
else if (window.ActiveXObject)
try
req = new ActiveXObject(«Msxml2.XMLHTTP»);
>
catch(e)
try
req = new ActiveXObject(«Microsoft.XMLHTTP»);
>
catch(e)
req = null;
>
>
>
return req;
>

Читайте также:  Html web pages to pdf

function GetData(url,callback)
req = new CreateReq;

if(req != null)
req.onreadystatechange = callback;
req.open(‘GET’, url, true);
req.send(null);
>
else alert(«Произошла ошибка..»);
>

Отправку GET запроса рассмотрим на примере получения кармы и силы с Хабра 🙂

function GetHabraCallback()
if(req.readyState == 4)
if(req.status == 200)
var xmlDoc = req.responseXML;
var karma = xmlDoc.getElementsByTagName(«karma»).item(0).firstChild.data;
var rating = xmlDoc.getElementsByTagName(«rating»).item(0).firstChild.data;
var place = document.getElementById(«data»);
if(place != null)
place.innerHTML = «Карма: «+karma+»
Рейтинг: «+rating+»;
>
>
>
return false;
>

GetHabraMe отправит GET запрос на habrahabr.ru/api/profile/lordeg, используя proxy.php и результат «вернет» в элемент с id “data”.

Отправка POST запроса происходит практически так же:

Источник

Кросс-доменные ajax-запросы и причем здесь php

Однажды я писал статью как создавать встраиваемые виджеты на нативном javascript и php. И все бы хорошо, но в ней не затронул один момент. Такие виджеты использовать на собственном сайте можно, но интереснее создавать их для сторонних ресурсов. Но в таком случае нужные данные браузер должен подгружать с другого домена — это и есть кросс-доменные ajax-запросы.

С точки зрения фронтенд-программистов кросс-доменные запросы ничем не отличаются от обычных. А вот на бекенде разница есть. Почему с ними не все так просто и как их реализовать — об этом читайте в статье.

Пробуем получить данные с другого домена

Для простоты рассмотрим get-запросы. Допустим, на сервере лежит некий html-файлик, который нам край как нужно загрузить ajax-ом с другого домена. Пусть это файл https://webdevkin.ru/examples/cross_domain/template.html. Откройте его и убедитесь, что он действительно доступен — вот ссылка (откроется в новой вкладке). Это обычный div с текстом «content from template.html».

А теперь давайте получим эту html-ку ajax-ом прямо из консоли браузера.

Не будем париться с нативным javascript-ом, а дернем запрос с помощью jQuery.get() и выведем в консоль то, что получили в ответ с сервера.

$.get('https://webdevkin.ru/examples/cross_domain/template.html', function(responce) );

Откройте прямо сейчас developer tools в браузере и на вкладке console выполните этот запрос.

Вы увидите примерно следующее

Все замечательно, отправили запрос, получили ответ. Казалось бы, что может быть проще? А теперь зайдите на любой другой сайт, где подключен jQuery и попробуйте проделать то же самое. Только не на https-сайт, почему — узнаете в конце статьи.

Я, например, проверял запросы на футбольном сайте bombardir.ru. И заодно подивился, какой только дряни не вываливается в консоль даже на таких достаточно известных сайтах. Впрочем, разговор не про это.

Выполните запрос с другого домена и Вы увидите в консоли уже не такую благостную картину. Говорит, невозможно загрузить, данных нет и вообще печаль.

Если откроете вкладку Network и найдете там соотвествующий запрос, то увидите, сервер даже вернул нам 200 ОК А содержимого файла нет. В чем подвох?

Что пошло не так и каково будет решение

Подвох в том, что политика интернетов не разрешает браузерам вытаскивать данные с каких угодно ресурсов. Кроме тех случаев, когда эти ресурсы сами заинтересованы в раздаче конкретных данных.
Наш случай именно такой. Чтобы дать разрешение на использование html-файлика откуда угодно, нужно при запросе оного файла отправлять http-заголовок Access-Control-Allow-Origin: *

Читайте также:  Adding html to wordpress header

Теперь вопрос, как это сделать. Если у Вас (или же у админов) есть доступ к nginx, то одним способом будет настроить прокидывание этого заголовка средствами веб-сервера. Вы идете к админам с соответствующей просьбой или гуглите сами нужные конфиги для Вашего веб-сервера.

Если же этого доступа нет, как например, у практически любого хостинг-провайдера на недорогом тарифе, то нужно выкручиваться самостоятельно. И здесь на помощь приходит php. Идея в том, чтобы закинуть нашу html-ку в php-файл, который и прокинет заголовок, и отдаст нужное содержимое.

Получится так, создаем файл template.php и первой строкой запишем php-команду

header('Access-Control-Allow-Origin: *');

То есть содержимое template.php будет таким, не забудьте про php-шные вопросы и скобки

Файл на webdevkin-е создан и лежит здесь (откроется в новой вкладке). Давайте теперь попробуем запросить его с другого домена и посмотрим, что будет

$.get('https://webdevkin.ru/examples/cross_domain/template.php', function(responce) );

Как видно, все работает прекрасно — файл загружен!

Заглянем на вкладку Network.
Обратите внимание, в блоке Response Headers появился интересующий нас заголовок Access-Control-Allow-Origin: *

В целом статья закончена. Осталось собрать мысли в кучу и добавить еще немного информации.

Обобщаем и подводим итоги

  • 1. Нельзя просто так запросить ajax-ом любой ресурс с другого домена
  • 2. Отправляйте заголовок Access-Control-Allow-Origin для всех ресурсов, к которым нужен доступ откуда угодно
  • 3. Делайте это средствами веб-сервера или php
  • 4. На php этот заголовок отправляется командой header(‘Access-Control-Allow-Origin: *’)
  • 5. Access-Control-Allow-Origin: * — разрешить доступ всем доменам, Access-Control-Allow-Origin: site.ru — только домену site.ru
  • 6. Access-Control-Allow-Origin отправляется в самом начале php-файла, еще до вывода других данных (как впрочем, и любые другие http-заголовки)
  • 7. «Ресурс» — это не только файл с html-разметкой, но и любой url, к которому идет ajax-запрос, например, получение json-данных или post-запрос на добавление строки в таблицу БД

И последнее, вынес отдельно. Я не зря просил выполнять запросы именно с http-сайта. С https не получится подгрузить данные с http по другой причине — mixed content. А webdevkin.ru пока что http-сайт (updated: уже нет, перенес webdevkin.ru на https)

Вот что увидите в консоли, попытавшись выполнить тот же запрос с любого https-сайта. Поэтому если Вы собираетесь заниматься встраиваемыми виджетами или чем-то подобным, Вам обязательно нужно поставить ssl-сертификат на своем сайте.

Анонсы статей, обсуждения интернет-магазинов, vue, фронтенда, php, гита.
Истории из жизни айти и обсуждение кода.

Источник

Кроссдоменные запросы (CORS) простая реализация

Несколько раз у меня уже возникала мысль о реализации кроссдоменных запросов между своими сервисами, однако толково настроить получалось плохо. Давайте уже наконец-то разберемся в этой теме.

Читайте также:  Просмотр файл doc на php

Для начала, рассмотрим пример:

У вас есть сайт «А», на пример, реализованный на Laravel и vue.js, который реализует определенную логику работы с какими-либо данными. Сейчас вы, в рамках одного сервиса (в данном случае, несколько микро сервисов решающих разные задачи для одного большого проекта), создаете сайт «Б», которому необходимо работать с той же базой данных и использовать часть функционала сайта «А».

Как решить этот вопрос? Естественно вы можете повторно реализовать необходимый функционал на сайте «Б» и подключиться к базе сайта «А». Но в этом есть свои существенные минусы, как минимум это:

  1. Вы, в рамках одной системы, дублируете код, который вы написали ранее.
  2. Вы используете прямой доступ к БД из двух разных мест, это существенно усложнит поиск ошибок, если такие возникнут и такой подход считается далеко не «лучшей практикой».

Так же, у вас есть ещё один вариант реализации (да, это первое, что пришло вам в голову) — jsonp. Но особенности этого метода заключаются в некоторой сложности реализации:

  1. Высокие требования к безопасности данного подхода
  2. Требования к изменению кода уже написанного ранее для сайта «А».
  3. Метод позволят только получить данные, если вам, к примеру требуется отправить информацию методом POST, при помощи jsonp вы этого сделать не сможете.
  4. Уязвимость к инъекциям — вы должны полностью доверять серверу, от которого получаете данные, ведь вы будете выполнять весь код, который вам от него приходит.

Но есть вариант лучше, проще, так как не требует внесения изменений на сайте «А» и является более безопасным подходом, это кроссдоменные запросы или CORS — Cross-origin resource sharing (в переводе: совместное использование ресурсов между разными источниками).

Суть метода очень проста: для того, чтобы серверу «А» получить или отправить данные на сервер «Б», достаточно на сервере «Б» установить «разрешение» на получение и ответ на запросы с сервера «А». Делается это следующим образом: в заголовках ответа на сервере «Б» вам необходимо установить следующие записи:

Источник

ajax Разрешить запросы между разными доменами — cross-domain — PHP

vedro-compota's picture

в начале скипта к которому предполагается разрешить доступ необходимо добавить:

header('Content-Type: application/json'); header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type'); header('Access-Control-Allow-Credentials: true');

Разрешить конкретные домены

Можно так, используя некий массив разрешённых доменов

подставлять домен, с которого приходит запрос, если тот разрешён:

$fromDomain = $_SERVER['HTTP_REFERER']; if (!empty($fromDomain) && in_array($fromDomain, $ALLOWED_DOMAINS)) < Request::SetAsync(); header('Access-Control-Allow-Origin: http://' . $fromDomain); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Allow-Methods: GET, PUT, POST, DELETE, OPTIONS'); header('Access-Control-Allow-Headers: Content-Type'); header('Access-Control-Max-Age: 1000'); header('Access-Control-Allow-Headers: Content-Type, Content-Range, Content-Disposition, Content-Description'); >

Разрешить тот, домен, с которого пришел запрос

Нужно установить Access-Control-Allow-Origin в тот же адрес, с которого пришел запрос. Например, так:

$origin = !empty($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : ''; header('Access-Control-Allow-Origin: ' . $origin);

— такое лучше делать только в режиме разработки.

——-
Оригинал этого замечательного решения я нашёл здесь (огромное спасибо автору): http://blog.lysender.com/2013/10/cross-d.

Key Words for FKN + antitotal forum (CS VSU):

Источник

Оцените статью