it-swarm.com.ru

AJAX междоменный вызов

Я знаю о AJAX междоменной политике . Поэтому я не могу просто позвонить " http://www.google.com " через HTTP-запрос ajax и отобразить Результаты где-то на моем сайте.

Я пробовал это с dataType "jsonp", который на самом деле будет работать, но я получаю синтаксическую ошибку (очевидно, потому что полученные данные не отформатированы в JSON)

Есть ли другая возможность получать/отображать данные из чужого домена? IFrames следуют той же политике?

64
jAndy

Единственный (простой) способ получения междоменных данных с использованием AJAX - это использовать язык на стороне сервера в качестве прокси, как отметил Энди Э . Вот небольшой пример того, как реализовать это с помощью jQuery:

JQuery часть:

$.ajax({
    url: 'proxy.php',
    type: 'POST',
    data: {
        address: 'http://www.google.com'
    },
    success: function(response) {
        // response now contains full HTML of google.com
    }
});

И PHP (proxy.php):

echo file_get_contents($_POST['address']);

Просто как тот. Просто знайте, что вы можете или не можете делать со скребками данных.

65
Tatu Ulmanen

Вам нужно будет динамически вставить тег скрипта на страницу, которая ссылается на данные. Используя JSONP, вы можете выполнить некоторую функцию обратного вызова, когда скрипт загрузится.

Страница википедии на JSONP содержит краткий пример; тег сценария:

<script type="text/javascript" src="http://domain1.com/getjson?jsonp=parseResponse">
</script>

вернет данные JSON, заключенные в вызов parseResponse:

parseResponse({"Name": "Cheeso", "Rank": 7})

(в зависимости от конфигурации скрипта getjson на domain1.com)

Код для динамической вставки тега будет выглядеть примерно так:

var s = document.createElement("script");
s.src = "http://domain1.com/getjson?jsonp=parseResponse";
s.type = "text/javascript";
document.appendChild(s);
18
alunny

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

function RunYQL(command, callback){
     callback_name = "__YQL_callback_"+(new Date()).getTime();
     window[callback_name] = callback;
     a = document.createElement('script');
     a.src = "http://query.yahooapis.com/v1/public/yql?q="
             +escape(command)+"&format=json&callback="+callback_name;
     a.type = "text/javascript";
     document.getElementsByTagName("head")[0].appendChild(a);
}

Если у вас есть jQuery, вы можете использовать вместо него $ .getJSON.

Образец может быть таким:

RunYQL('select * from html where url="http://www.google.com/"',
       function(data){/* actions */}
);
16
Alexandre Vicente

К сожалению (или к счастью) нет. Междоменная политика существует по определенной причине: если бы ее было легко обойти, то она не была бы очень эффективной в качестве меры безопасности. Кроме JSONP, единственная опция - прокси страниц, используя ваш собственный сервер .

С iframe они подчиняются той же политике. Конечно, вы можете отображать данные из внешнего домена, вы просто не можете ими манипулировать.

11
Andy E

Я использую этот код для междоменного вызова ajax, я надеюсь, что он поможет больше, чем один здесь. Я использую библиотеку Prototype, и вы можете сделать то же самое с JQuery, Dojo или чем-то еще:

Шаг 1: создайте новый файл js и поместите этот класс внутрь, я назвал его xss_ajax.js

var WSAjax = Class.create ({
    initialize: function (_url, _callback){
        this.url = _url ;
        this.callback = _callback ;
        this.connect () ;
    },
    connect: function (){
        var script_id = null;
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script.setAttribute('src', this.url);
        script.setAttribute('id', 'xss_ajax_script');

        script_id = document.getElementById('xss_ajax_script');
        if(script_id){
            document.getElementsByTagName('head')[0].removeChild(script_id);
        }

        // Insert <script> into DOM
        document.getElementsByTagName('head')[0].appendChild(script);
    },
    process: function (data){
        this.callback(data) ;
    }

}) ;

Этот класс создает динамический элемент сценария, атрибуты src которого предназначены для вашего поставщика данных JSON (фактически JSON-P, поскольку ваш удаленный сервер должен предоставлять данные в этом формате :: call_back_function (// json_data_here) ::, поэтому при создании тега сценария JSON будет напрямую вызываться как функция (мы поговорим о передаче имени метода обратного вызова на сервер на шаге 2), основная идея этого заключается в том, что сценарии, подобные элементам img, не связаны с ограничениями SOP.

Шаг 2: на любой html-странице, где вы хотите получить JSON асинхронно (мы называем это AJAJ ~ Asynchronous JAvascript + JSON :-) вместо AJAX, в котором используется объект XHTTPRequest), выполните следующие действия:

//load Prototype first
//load the file you've created in step1


var xss_crawler = new WSAjax (
     "http://your_json_data_provider_url?callback=xss_crawler.process"
 ,   function (_data){
            // your json data is _data and do whatever you like with it 
        }) ;

Вы помните обратный вызов на шаге 1? поэтому мы передаем его на сервер, и он возвращает JSON, встроенный в этот метод, поэтому в нашем случае сервер вернет корректный код javascript xss_crawler.process (// the_json_data), помните, что xss_crawler является экземпляром класса WSAjax. Код сервера зависит от вас (если он ваш), но большинство провайдеров данных Ajax позволяют указывать метод обратного вызова в параметрах, как мы это делали ... В Ruby on Rails я только что сделал

render :json=>MyModel.all(:limit=>10), :callback => params[:callback],:content_type => "application/json"

и все, теперь вы можете извлекать данные из другого домена из ваших приложений (виджетов, карт и т. д.), только в формате JSON, не забывайте.

Я надеюсь, что это было полезно, спасибо за ваше терпение :-), мир и извините за форматирование кода, это не работает хорошо

4
R Francky

после некоторых исследований единственное «решение» этой проблемы - позвонить:

if($.browser.mozilla)
   netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');

это спросит пользователя, разрешает ли он продолжить работу веб-сайта. После того, как он подтвердил это, все вызовы Ajax, независимо от их типа данных, будут выполнены.

Это работает для браузеров Mozilla, в IE <8 пользователь должен разрешить междоменный вызов Аналогичным образом, некоторую версию необходимо настроить в настройках браузера.

chrome/Safari: я не нашел флаг настройки для этих браузеров до сих пор.

было бы неплохо использовать JSONP в качестве типа данных, но в моем случае я не знаю, нужен ли мне домен. Доступ к данным в этом формате.

Еще один способ - использовать HTML5 postMessage, который работает и в междоменных областях, но я не могу Позволить себе обречь моих пользователей на браузеры HTML5.

4
jAndy

Если вы используете скрипт php для получения ответа от удаленного сервера, добавьте эту строку в начале:

header("Access-Control-Allow-Origin: *");
3
akadi81

JSONP - лучший вариант, на мой взгляд. Попытайтесь выяснить, почему вы получаете синтаксическую ошибку - вы уверены, что полученные данные не являются JSON? Тогда, может быть, вы неправильно используете API.

Другой способ, которым вы могли бы воспользоваться, но я не думаю, что это применимо в вашем случае, это иметь на странице iFrame, который находится в домене, который вы хотите вызвать. Пусть он сделает вам звонки, а затем использует JS для связи между iFrame и страницей. Это позволит обойти междоменный домен, но только если вы можете иметь src iFrame в домене, который хотите вызвать.

2
Nir

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

Сначала создайте серверный скрипт для обработки ваших запросов. Что-то вроде http://www.example.com/path/handler.php

Вы будете вызывать его с параметрами, например: .../handler.php? Param1 = 12345 & param2 = 67890

Внутри него, после обработки полученных данных, output:

document.serverResponse('..all the data, in any format that suits you..');
// Any code could be used instead, because you dont have to encode this data
// All your output will simply be executed as normal javascript

Теперь в клиентском скрипте используйте следующее:

document.serverResponse = function(param){ console.log(param) }

var script = document.createElement('script');
script.src='http://www.example.com/path/handler.php?param1=12345&param2=67890';
document.head.appendChild(script);

Единственным ограничением этого подхода является максимальная длина параметров, которые вы можете отправить на сервер. Но вы всегда можете отправить несколько запросов.

1
AlexTR

Вы можете использовать технологию CORS для настройки обоих серверов (сервера, на котором работает Javascript, и внешнего сервера API)

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

стр .: ответ https://stackoverflow.com/a/37384641/6505594 также предлагает этот подход, и он открывает внешний API-сервер для всех остальных, чтобы он вызывал его.

0
morhook