我了解 AJAX 跨域策略。所以我不能只是通过 ajax HTTP 请求调用“ http://www.google.com ”并在我网站的某处显示结果。
我用 dataType "jsonp" 尝试过,这实际上可以工作,但我收到一个语法错误(显然是因为接收到的数据不是 JSON 格式的)
是否还有其他可能从外国域接收/显示数据?iFrame 遵循相同的策略?
我了解 AJAX 跨域策略。所以我不能只是通过 ajax HTTP 请求调用“ http://www.google.com ”并在我网站的某处显示结果。
我用 dataType "jsonp" 尝试过,这实际上可以工作,但我收到一个语法错误(显然是因为接收到的数据不是 JSON 格式的)
是否还有其他可能从外国域接收/显示数据?iFrame 遵循相同的策略?
正如Andy E指出的那样,使用 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']);
就那么简单。请注意您可以或不能对抓取的数据做什么。
您需要将脚本标记动态插入到引用数据的页面中。使用 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);
您可以使用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 */}
);
不幸(或幸运)不是。跨域策略的存在是有原因的,如果它很容易绕过它,那么它作为一种安全措施就不会非常有效。除了 JSONP,唯一的选择是使用您自己的服务器代理页面。
对于 iframe,它们受相同的策略约束。当然,您可以显示来自外部域的数据,只是无法对其进行操作。
我使用这段代码进行跨域ajax调用,我希望它在这里可以帮助不止一个。我正在使用 Prototype 库,你可以用 JQuery 或 Dojo 或其他任何东西做同样的事情:
第一步:新建一个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:在您想要异步拉取 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 格式,不要忘记。
我希望它有帮助,感谢您的耐心 :-),对于代码格式的和平和抱歉,它不能正常工作