前端跨域知识简介

前端跨域知识简介

灵感

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

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

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

跨域方法 -- 单向

jsonp

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

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页面之间可以自由调用。

参考资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏菩提树下的杨过

再谈web开中几种经典的大文件上传组件

1.aspnetupload 这是国人开发的一款收费.net控件,官网http://www.aspnetupload.net/ (不过也有一个免费版本的,允许上...

22160
来自专栏IMWeb前端团队

再见2015 再见cmd

本文作者:IMWeb yisbug 原文出处:IMWeb社区 未经同意,禁止转载 2015年已经快要过去了,你是否还在使用有着十几年历史的cmd命令行...

33390
来自专栏FreeBuf

文件监控程序V2.0改进版(网站防挂马好手)

前言 技多不压身,多掌握几种不同的编程语言,不但有助于开拓我们的视野,还可以让我们在工作时,自己写一些小程序来帮我们减少工作量。 前段时间给一个客户维护服务器,...

62950
来自专栏美团技术团队

LsLoader——通用移动端Web App离线化方案

背景 由于JavaScript(以下简称JS)语言的特性,前端作用域拆分一直是前端开发中的首要关卡。从简单的全局变量分配,到RequireJS实现的AMD模块方...

470170
来自专栏生信技能树

点击此文,无需转发,即可下载上千个免费R包

写在前面: 谨以此文献给那些“奋斗”在转发送别人资源,为了博人眼球,而践踏别人的辛勤的劳动成果的公众号们。 当然了,R包本来就是免费的,你只是不会下载而已,所以...

43780
来自专栏FreeBuf

护卫神主机大师提权漏洞利用分析

护卫神·主机大师支持一键安装网站运行环境(IIS+ASP+ASP.net+PHP5.2-5.6+MySQL+FTP+伪静态+PhpMyAdmin),并可在线开设...

29900
来自专栏IT技术精选文摘

解Bug之路-记一次JVM堆外内存泄露Bug的查找

14630
来自专栏程序员的碎碎念

如何解决Python包依赖问题

以简洁高效(指编程较为高效, 而不是运行速度)出名的Python, 在包依赖问题上有时候让人挠头.

21820
来自专栏PHP在线

Web安全实战

前言 本章将主要介绍使用Node.js开发web应用可能面临的安全问题,读者通过阅读本章可以了解web安全的基本概念,并且通过各种防御措施抵御一些常规的恶意攻击...

372100
来自专栏解Bug之路

解Bug之路-记一次JVM堆外内存泄露Bug的查找 顶

JVM的堆外内存泄露的定位一直是个比较棘手的问题。此次的Bug查找从堆内内存的泄露反推出堆外内存,同时对物理内存的使用做了定量的分析,从而实锤了Bug的源头。笔...

10140

扫码关注云+社区

领取腾讯云代金券