前端跨域知识简介

前端跨域知识简介

(2年前旧文,历来没发表过,最近从新整理了一下代码,弄了个steamer-cross)html

原文地址前端

灵感

差很少2年前,因为业务须要,了解各类各样不一样的跨域方式。但因为各类方式千奇百怪,我以为有必要将各类方法封装起来,方便使用,弄了个简单的跨域使用库,里面包含各类跨域的使用函数,都存放在steamer-cross v1.0分支里。但2年事后,IE8如下的浏览器已经逐渐淡出市场,基本上跨域的方案能够由postMessage一统天下,因而在MessengerJS启发下,本身写了一个steamer-cross v2.0版本,更灵活的用法,且兼顾父子窗口之间互相传递数据。git

v1.0版本可能有bug,仅供学习参考,v2.0已写测试样例,能够test文件夹中看到,文档不清楚的地方,也能够参考test/index.html的写法。github

本主不会详细述说各类方法的具体实现,具体的办法能够点击后文参考资料里面的三篇文章。本文只会说起实现过程当中的一些坑,以及框架的实现办法。具体的实现方法,能够参考steamer-cross v1.0版本中的文件,各类办法的实现,能够看对应文件夹里面的文件。ajax

跨域方法 -- 单向

jsonp

这是最直观的办法,只须要一个页面,在页面内包含一个指向数据页面的script tag,而后在src后面多加一个回调函数便可以获取数据。json

cross origin resource sharing (cors)

这个办法先后端都涉及,所以前端的同窗须要后端的配合。其实质只是一个ajax,能够接收除了post和get以后的其它服务器请求例如put。后端须要修改的是.htaccess文件。加入如下一句后端

Header set Access-Control-Allow-Origin *复制代码

符号*表明接收任意的HTTP请求,你也能够经过修改,限制接受请求的域名或者IP地址。跨域

另一个隐藏坑是,ie10如下的浏览器是不支持的。值得注意的是,ie8和ie9是经过XDomainRequest来进行CORS通讯的。XDomainRequest一样支持get和post方法。对象详细内容请见参考资料。浏览器

XDomainRequest的另外一个坑是,当发送POST请求的时候,没法设置Header,如安全

xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");复制代码

这可能致使后台无法辨认POST数据。若是是PHP的话,后台须要特殊的处理,例如

if(isset($HTTP_RAW_POST_DATA))
{
    parse_str($HTTP_RAW_POST_DATA, $output);
    echo json_encode($output);
}复制代码

CORS支持状况:Chrome 4 , Firefox 3.5 , IE 8~9(XDomainRequest), IE 10+ , Opera 12 , Safari

location.hash

这个办法坑比较多,网上的办法会有些问题。这个办法须要三个页面,分别是主调用页(index.html), 数据页(data.html),和代理页(proxy.html)。实质的结构是,index.html里有一个iframe指向data.html,而data.html里又有一个iframe指向proxy.html。要注意的是,index.html和proxy.html主域和子域都相同,只有data.html是异域,所以当data.html生成数据时,将数据放在proxy.html连接的hash(#)后面,而后再由proxy.html里的代码经过parent.parent这样的调用,将数据放到proxy.html的祖父index.html的连接上面。

大多数教程都是停留在这一步。这是不够的,还须要在index.html里面设置一个setInterval去监听index.html中#的变化,进而获取数据。听说有些高端浏览器里面能够直接用hashchange来监听,但低端的话最好仍是用setInterval。所以框架里面用setInterval实现。

window.name

因为window.name在iframe的src的变化时不会改变,因此这个办法也能够用于跨域。这个方式虽然也须要跟location.hash也须要三个页面,但proxy.html的做用很是次要。因为data.html可以直接对window.name写值,所以写值完毕后,只须要将src改为与index.html主域和子域一致的页面,就可让index.html直接调用了。也有不须要proxy页面的写法,将iframe的src写成"about:blank;"就能够了。

跨域方法 -- 双向

document.domain

这个办法对于主调用页(index.html)和数据页(data.html)而言是双向的,即两个页面均可以获得对方的数据(主要是DOM元素)。实质就是index.html包含一个指向data.html的iframe,而后在data.html中改变document.domain,使之和index.html的document.domain是同样的,这样就可使两个页面互相调用对方的数据。惟一的缺点是只能应用于子域不一样,但主域相同的两个页面。

postMessage

网上大部份教程都只教从index.html传数据到data.html。其实data.html也能够发数据到index.html。实现方法同样,只要在data.html里面发送的地址跟index.html的地址同样就能够了。不然浏览器会报错。这是比较优秀的一个办法,缺点是旧式浏览器并不支持。

window.navigator

这是ie6和ie7的一个安全bug。目前彷佛尚未补丁打上,因此主页面和iframe页面之间能够自由调用。

参考资料

相关文章
相关标签/搜索