ajax请求json数据跨域问题(转)

时间:2022-04-23 11:11:10

一、后台代理技术

由服务器端向跨域下的网站发出请求,再将请求结果返回给前端,成功避免同源策略的限制。

具体操作如下:

1、在localhost:81/a.html中,向同源下的某个代理程序发出请求

$.ajax({

    url:'/proxy.php?name=hello&info=information',   //服务器端的代理程序

    type:'GET',

    success:function (){}

})

2、在代理程序proxy.php中,向非同源下的服务器发出请求,获得请求结果,将结果返回给前端。

<?php

$name=$_GET['name'];

$info = $_GET['info'];

$crossUrl = 'http://b.com/sub?name='.$name;   //向其他域下发出请求

$res = file_get_contents($crossUrl);

echo $res;

 ?>

二、Jsonp

为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

JSONP的客户端具体实现:

(1)远程服务器remoteserver.com根目录下有个remote.js文件代码如下:

localHandler({"result":"我是远程js带来的数据"});

(2)本地服务器localserver.com下有个jsonp.html页面代码如下:

<head>
<title></title>
<script type="text/javascript">
var localHandler = function(data){
alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
};
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>

(3)一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?

解决:服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成js脚本并响应了。

-- 本地服务器localserver.com下有个jsonp.html页面代码如下:

<script type="text/javascript">    // 得到航班信息查询结果后的回调函数
var flightHandler = function(data){
alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
}; // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://flightQuery.com/jsonp/flightResult.aspx? code=CA1998&callback=flightHandler"; // 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url); // 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</head>

-- 远程服务器很聪明,这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html

(4)jQuery如何实现jsonp调用?

<script type="text/javascript">
jQuery(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "http://flightQuery.com/jsonp/flightResult.aspx?
code=CA1998",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){
alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
},
error: function(){
alert('fail');
}
});
});
</script>

  为什么我这次没有写flightHandler这个函数呢?而且竟然也运行成功了!这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时,自动帮你生成回调函数并把数据取出来供success属性方法来调用

(5)补充

  1、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装;

  2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。

  3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。

  4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

  总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!

参考网址:http://kb.cnblogs.com/page/139725/

三、XmmlHttpRequest2(XHR2)

HTML5提供的XMLHttpRequest Level 2已经实现了跨域访问以及其他的一些新功能

这需要在远程服务器端添加如下代码

header('Access-Control-Allow-Origin:*'); //*代表可访问的地址,可以设置指定域名

header('Access-Control-Allow-Methods:POST,GET');

这样在客户端使用常规的AJAX代码即可。

参考网址:http://www.php186.com/content/article/ajax/24580.html

四、总结

代理实现最麻烦,但使用最广泛,任何支持AJAX的浏览器都可以使用这种方式。

JSONP相对简单,但只支持GET方式调用。

XHR2最简单,但只支持HTML5,如果你是移动端开发,可以选择使用XHR2。