1、什么是跨域访问?
(1).同一父域名,不同域名之间的访问,包括同域名不同端口,如xx.com与yy.xx.com,xx:8088.com与xx:9200.com
(2).完全不同的域名,如xx.com与yy.com
2、我们为什么要解决跨域?
(1) 我们自己的系统需要把不同资源放在不同服务器上,如AJAX请求,邮件系统获取通讯录人信息;
(2) 自己的系统访问别人的系统。
3、相关的解决方案?
XMLHttpRequest是浏览器的接口 最早是IE5上出现的
老版本问题:
(1)只支持文本数据的传送,无法用来读取和上传二进制文件。
(2) 传送和接收数据时,没有进度信息,只能提示有没有完成。
(3) 受到"同域限制"(Same Origin Policy),只能向同一域名的服务器请求数据。
新版本: Cross-origin resource sharing,简称CORS:浏览器必须支持这个功能,而且服务器端必须同意这种"跨域"IE10以及以上的
服务器端设置Access-Control-Allow-Origin
IE8-IE9进行跨域请求时:
var
xdr =
new
XDomainRequest();
IE5-IE6采用
new ActiveXObject("Microsoft.XMLHTTP");
(1)同父或同根域名,可以采用document.domain="根域名",两个服务中的页面都进行设置,对于最新y
a、 当浏览器不支持ajax访问时,可以采用iframe的方式,调用请求方的proxy.htm页面,在proxy.htm页面进行访问,在proxy.htm加载完成后,调用相关ajax访问
http:// YY/A.htm
<body>
<iframe src="http://A.XX/proxy.htm"> </ifame>
<script>
调用proxy.htm中方法,传入调用的接口
</script>
b、对于像
(3) 采用在服务器端访问不同的域名,但是这样会增加请求与转向
(4)利用JSONP,JSON with padding 用img script 与link进行跨域请求 <script src="http://a/b/xx?jsonp=callback"></script>,其中jquery也有相应实现;
如:
1. $.getJSON
<script> $(document).ready(function(){ $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function(data){ $.each(data.items, function(i,item){ $("<img/>").attr("src", item.media.m).appendTo("#images"); if ( i == 3 ) return false; }); }); }); </script> jsoncallback=?,其中?会自动替换为function(data)函数。 2. $.ajax $.ajax({ dataType: 'jsonp', data: 'id=10', jsonp: 'jsonp_callback', url: 'http://www.yiwuku.com/getdata', success: function () { // do stuff }, });(5) 采用location.hash="#asdf"的值进行处理
一个 URL 由几部分组成,如下图 2 所示:
图 2. URL 组件
通常,URL 的任何更改都会导致加载新的页面。唯一的例外是 hash 值的变化。任何 URL 的 hash 更改都不会导致页面刷新。许多 Web 2.0 网站中都已经开始广泛使用 Hash,以标记部分刷新页面时的每一个步骤。在跨域通信中,hash 是一笔宝贵的资产。虽然在获取对方 hash 值方面有一些限制,但来自不同源点的文件可以设置对方的 URL,包括 hash 值。文档相互之间可以使用 hash 传送信息。图 3 显示了一个示例。
图 3. 使用 URL.hash(fragment id) 进行通信
在图 3 中,当 A 想要向 B 发送信息时,它可以修改 B 的 hash 值,如清单 1 所示:
清单 1. 通过 url.hash 发送信息
function sendMsg(originURL, msg){ var data = {from:originURL, msg:msg}; var src = originURL + “#” + dojo.toJson(data); document.getElementById('domainB').src=src; } |
B 中的函数将轮询自身的 hash 值,找出 A 发送的是什么,然后它可以用同样的方式回复 A。如果 A 想接收这条消息,也需要轮询其本身的 hash 值。
清单 2. 监视 url.hash 并从中接收信息
window.oldHash=""; checkMessage = function(){ var newHash = window.location.hash; if(newHash.length > 1){ newHash = newHash.substring(1,newHash.length); if(newHash != oldHash){ oldHash = newHash; var msgs = dojo.fromJson(newHash); var origin = msgs.from; var msg = msgs.msg; sendMessage(origin, "Hello document A"); } } } window.setInterval(checkMessage, 1000); sendMessage = function(target, msg){ var hash = "msg="+ msg; parent.location.href= target + “#” + hash; } (6)
父文档将监听消息事件。当消息到达时,会先检查它是否来自 清单 10. 通过 HTML5 的新方法接收消息
清单 10 中的示例代码可以在 Firefox 3+、Internet Explorer 8、Google Chrome 2、Opera 9+ 以及 Safari 4 中运行。它使得来自不同来源的文档之间的通信变得更加方便。此外,如果不希望自己的文档收到来自其他文档的任何消息,那么不要添加事件监听器并删除所有消息。 |
像 JSONP 一样,这种方法也有一个长度限制,但它可以更好地处理错误。一些特殊字符,比如问号(?),是 URL 中的保留字符,应先对这些字符进行编码。
清单 3. 通过 url.hash 发送包含特殊符号的信息
function sendMsg(originURL, msg){ … var src = originURL + “#” + encodeURI (dojo.toJson(data)); … } |
接收时,应先进行解码。
清单 4. Receiving message containing special characters
function checkMsg(){ … var msgs = decodeURI(dojo.fromJson(newHash)); … } 还可用hash进行ajax的前进与后退的处理 |