一、跨域定义及类型
定义:只要协议、域名、端口有任何一个不同,都被当做不同的域。
类型:(由于浏览器的同源策略)
1)浏览器中不同域的框架之间不能进行js交互操作;
2)不能通过ajax去请求不同源中的文档;
注意:由于协议和端口造成的跨域,前端无法解决。
跨域处理:
1、document.domain
用于处于跨域的第一种类型,iframe类型。
例子:
A页面:http://www.baidu.com/a.html
B页面:http://www.google.com/b.html(作为iframe页面嵌入到A页面中)
A页面中:
var iframe = document.getElementById('iframe'); var win = iframe.contentWindow; var doc = win.document; console.log(doc); //报错
结论:A页面可以得到B页面的window对象,但无法获取window对象的属性和方法;
使用document.domain设置两个页面的主域相同。(注意:主域只能设置为自身或者更高一级的父域)
A页面设置document.domain = ‘baidu.com’;B页面设置document.domain = ‘baidu.com’;
这样便可以进行父子域的js交互。
2.location.hash
父窗口可以读写iframe的url,子窗口也可以读写父窗口的url(俩页面在不同域下IE、chrome不允许修改parent.location.hash),hash是跟随在url后面的#及其后面的内容,一般用作浏览器锚点定位。虽然hash不参与http请求,但会产生浏览器记录。
可以通过hash传参。
A页面为父页面(http://www.baidu.com/a.html),B页面为子页面( http://www.google.com/b.html),两者的域不同,要兼容IE、chrome的无法获取IE、chrome的无法获取parent.location.hash的情况,代码如下:
try{ parent.location.hash = 'data'; }catch(e){ var Iframe = document.createElement('iframe'); Iframe.style.display = 'none'; Iframe.src = 'http://www.baidu.com/proxy.html#data';//子Iframe的域需要与A页面相同 document.body.appendChild(Iframe); }
proxy.html页面的设置:
parent.parent.location.hash= self.location.hash.substring(1);
3.通过postMessage跨域
A页面(baidu.com),B页面(google.com);
A页面代码:
<script> var iframe = document.getElelmentById('iframe'); var targetOrigin = 'www.google.com';//接受着的范围 iframe.contentWindow.postMessage('Hello World', targetOrigin); </script>
postMessage方法的API:otherWindow.postMessage(messageBody, targetOrigin);
otherWindow:其他窗口;
messageBody:消息主体;
targetOrigin:接受者的范围;
B页面获取方法:
function onMessage (event) { var data = event.data;//消息 var origin = event.orgin;//发送源的地址 var source = event.source; //发送源的window对象 if(origin == 'http://www.baidu.com'){ //doing something } } if(typeof window.addEventListener != 'undefined') { window.addEventListener('message', onMessage, false); }else if(typeof window.attachEvent != 'undefined') { window.attachEvent('onmessage', onMessage); }
4、通过jsonp跨域
原理:script标签引用资源不受浏览器同源策略的限制。script的src属性可以访问跨域的js脚本,因此服务器不再返回json数据,而是返回一段调用某函数的js代码,在src进行了调用。
对象:不针对不同域的iframe页面通信,而是希望从服务端获取数据。
例子:A页面(a.html)需要通过ajax获取一个不同域上的json数据。假设json数据的地址为http://www.yoriluo.top/data.php,则a.html的代码如下:
<script> function doSomething(jsondata) { ... } </script> <script src="http://www.yoriluo.top/data.php?callback=doSomething"></script>
其中http://www.yoriluo.top/data.php页面一定是返回可执行的js文件,需要与后端商量好。
jsonp只支持GET请求,只支持HTTP请求。
5.CROS跨域(未深入)
使用方法:与ajax相同
普通ajax:
function ajax(){ var xhr = new XMLHttpRequest(); xhr.open('GET', 'api/...’, true); 本地域的资源地址 xhr.send(); }
使用CROS:
function ajax(){ var xhr = new XMLHttpRequest(); xhr.open('GET', '‘http://segmentfault.com/u/trigkit4/’, true); //地址为你想跨域访问资源的地址 xhr.send(); }
CROS跨域需要与服务端协商好,需在服务端设置 Access-Control-Allow-Origin;
6.window.name跨域(未深入)
使用父窗口与frame窗口的window.name的值相同,但不支持不同源的共享。