AJAX跨域调用

时间:2010-04-01 08:06:04

标签: javascript jquery ajax json jsonp

我了解AJAX跨域策略。 所以我不能只通过ajax HTTP请求和显示调用“http://www.google.com” 在我的网站上某处的结果。

我尝试使用dataType“jsonp”,实际上可以工作,但我得到一个语法错误(显然是因为收到的数据不是JSON格式化的)

是否还有其他可能从外国域接收/显示数据? iFrame遵循相同的政策?

11 个答案:

答案 0 :(得分:65)

使用AJAX获取跨域数据的唯一(简单)方法是使用服务器端语言作为Andy E所指出的代理。这里有一个小例子如何使用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']);

这很简单。请注意您使用已删除数据可以做什么或不做什么。

答案 1 :(得分:19)

您需要在引用数据的页面中动态插入脚本标记。使用JSONP,您可以在脚本加载时执行一些回调函数。

JSONP上的维基百科页面有一个简明的例子;脚本标签:

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

会返回调用parseResponse

的JSON数据
parseResponse({"Name": "Cheeso", "Rank": 7})

(取决于domain1.com上getjson脚本的配置)

动态插入标记的代码如下:

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

答案 2 :(得分:16)

您可以使用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 */}
);

答案 3 :(得分:11)

不幸的是(或幸运的是)没有。跨域策略是有原因的,如果它很容易解决它,那么它作为安全措施就不会非常有效。除了JSONP之外,唯一的选择是proxy the pages using your own server

使用iframe,它们遵循相同的政策。当然,您可以显示来自外部域的数据,您无法操纵它。

答案 4 :(得分:4)

在做了一些研究之后,这个问题的唯一“解决方案”就是打电话:

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

这将询问用户是否允许网站继续。在他确认之后,全部 ajax调用无论它的数据类型都会被执行。

这适用于Mozilla浏览器,在IE&lt;如图8所示,用户必须允许跨域调用 以类似的方式,某些版本需要在浏览器选项中进行配置。

chrome / safari:到目前为止,我没有为这些浏览器找到配置标志。

使用JSONP作为数据类型会很好,但在我的情况下我不知道我是否需要一个域 访问支持该格式的数据。

另一个镜头是使用HTML5 postMessage,它也适用于跨域,但我不能 让我的用户陷入HTML5浏览器。

答案 5 :(得分:4)

我使用此代码进行跨域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约束。

Step2:在你想要异步提取JSON的任何html页面中(我们称之为AJAJ~Asynchronous JAvascript + JSON :-)而不是使用XHTTPRequest对象的AJAX)如下所示

//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格式,不要忘记。

我希望它有所帮助,感谢您的耐心:-),和平并抱歉代码格式化,它不能正常工作

答案 6 :(得分:3)

如果您使用php脚本从远程服务器获取答案,请在开头添加此行:

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

答案 7 :(得分:2)

在我看来,JSONP是最好的选择。试着弄清楚为什么会出现语法错误 - 你确定收到的数据不是JSON吗?那么也许你会以某种方式使用API​​。

您可以使用的另一种方式,但我不认为它适用于您的情况,在页面中有一个iFrame,其中src位于您要调用的域中。让它为你做调用,然后使用JS在iFrame和页面之间进行通信。这将绕过跨域,但前提是您可以在要调用的域中拥有iFrame的src。

答案 8 :(得分:1)

这是一种简单的方法,可以帮助您完成任务,而不必使用任何花哨的东西,甚至是JSON。

首先,创建一个服务器端脚本来处理您的请求。像http://www.example.com/path/handler.php

这样的东西

您将使用参数调用它,例如:... / handler.php?param1 = 12345&amp; param2 = 67890

在其中,处理完收到的数据后,输出

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);

此方法的唯一限制是您可以发送到服务器的参数的最大长度。但是,您始终可以发送多个请求。

答案 9 :(得分:0)

您可以使用CORS技术配置两台服务器(运行Javascript的服务器和外部API服务器)

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

p.s:答案https://stackoverflow.com/a/37384641/6505594也建议采用这种方法,并且打开外部API服务器给其他人调用它。

答案 10 :(得分:-3)

我在2天内遇到了同样的问题,我找到了解决方案,并且在google搜索后很优雅。 我需要一些小部件客户端的xss Ajax,它将数据流从层网站拉到我的Rails应用程序。 here's how I did.

相关问题