以下都是自己看了些资料还有博客什么的结合起来的理解,如果有不对或者有问题的地方请指出,多谢了
之前在面试的时候也被问起过,当时是一点都没听说过,后来就是把这个问题给记录了,不过没细究,这回偶然需要解决一个问题,大致的问题就是拿到一个优酷视频的一个地址,这个地址就是在视频下面点击分享里有的,是<embed>的一组标签,然后我网上找了一下,找到了优酷视频的解决办法,我试着用ajax去获取一个优酷地址上的时候,提示错误,代码如下,
$.ajax({
type: 'GET',
url: youkuUrl2,
dataType : "json",
error:function(){
console.log("出现错误");
},
success:function(datas){
console.log(datas);
},
});
XMLHttpRequest cannot loadhttp://api.stackoverflow.com/1.1/stats. No 'Access-Control-Allow-Origin' header is present on the requestedresource. Origin 'null' is therefore not allowed access
百度了下,这个其实就是跨域访问的错误,再来介绍下有关跨域访问的东西。同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性。也就是说,受到请求的 URL 的域必须与当前 Web 页面的域相同。然后再提两个相关的东西。
1.在浏览器中不能直接来跨域访问,而在服务器端没有跨域安全限制
2.同源策略不阻止动态脚本元素插入,脚本访问可以跨域
所以一个方法就是后台处理,一个是前台处理,下面就在说说下前台这边的处理。
一、客户端
在写的页面中有时候会引用类似jQuery的库,我们会使用一些cdn啥的,或者是官网提供的一个地址,比如<scriptsrc="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>,这里面就是引用了一个另外一个域,所以类似的也可以使用这样的办法。这个就是用jsonp来实现这个功能,首先先说下,json和jsonp的区别。
(1)Json是一种数据传输的格式,js有着很好的原生支持,具体的可以看下面的这个例子
var person = {
"Name": "Bob",
"Age": 32,
"Company": "IBM",
"Engineer": true
}
(2)而jsonp则不是一种数据传输格式,他的全名是(JSON with Padding),他需要后端的一点处理支持,实现的大概看如下的
在页面中加入一个<script>
<script src=" http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=myCallback
"></script>
这里面你可以先在浏览器中输入
http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US
可以在浏览器中看到一组
json
格式的数据,在里面加上了一个
callback=myCallback
,其实的作用就是执行回调函数
myCallback
,将由服务端获得的数据,作为参数传递到函数
myCallback
中,而回调函数
myCallback
则是在客户端浏览器中申明。附上完整的代码
<script type="text/javascript">
function myCallback(data){
console.log(data);
}
</script>
<script src=" http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=myCallback"></script>
上面的第二个<script>也可以修改为下面代码,是更多的利用了jQuery封装好的
$.ajax({
type: 'GET',
url: 'http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=myCallback',
dataType:'jsonp',
jsonp: "false",
jsonpCallback:" myCallback",
success:function(data){
console.log(data);
}
});
而这个需要后端的一点支持,比如原本服务端的json输出是格式为{data:[]};要修改为接受一个参数,假设参数名称为callback,然后你访问服务端的链接变成了:http://url?callback=functionname,服务端返回:functionname( {data:[]} ),当你用向DOM插入script节点的方式插入服务端传来的数据时,相当于运行了服务端的一个JS里面的函数。functionname就获得了服务端生成的数据。如果在后端没有实现这一功能,他返回的将任然是一个json数据,浏览器将会报错,提示格式的问题。不过还是有其他的办法来解决这个问题的,就是利用第三方的代理,比如雅虎的YQL,关于这个问题,将在下一个文章里说明。
二、服务端
服务端的方法:用服务器端的XmlHttpRequest代理实现跨域访问,下面的几个图就是说明了一些有关于的问题,貌似是来自于Yahoo的,对于服务端的实现我也没怎么太多深究,就大概看了下面的几个图
(1)使用XmlHttpRequest访问同一域名下的资源:
(2)使用XmlHttpRequest跨域访问资源:
(3)用服务器端的XmlHttpRequest代理来跨域访问资源:
这里在列几个在其他博文上找到提供现成jsonp服务的网站
1.Geonames API:邮编的位置信息:
http://www.geonames.org/postalCodeLookupJSON?postalcode=10504&country=US&callback=?
2.Flickr API:来自 Flickr的最新猫图片
http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any
&format=json&jsoncallback=?
3.Yahoo Local Search API:在邮编为 10504的地区搜索比萨:
http://local.yahooapis.com/LocalSearchService/V3/localSearch?appid=YahooDemo&query=pizza
&zip=10504&results=2&output=json&callback=?
参考博客:
[1] http://www.nowamagic.net/ajax/ajax_KonwHowToCrossDomain.php
[2] http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html
[4] http://bbs.csdn.net/topics/350126231
[5] http://www.ibm.com/developerworks/cn/web/wa-aj-jsonp1/
[6] http://www.cnblogs.com/chopper/archive/2012/03/24/2403945.html