父子页面之间跨域通信的方法
2014-08-19 22:42
211 查看
父子页面之间跨域通信的方法
2014/08/08 | 分类: WEB前端, 开发 | 1条评论 | 标签: 前端开发
原文出处: 腾讯TID - lyndon 欢迎分享原创到伯乐头条
由于同源策略的限制,JavaScript跨域的问题,一直是一个比较棘手的问题,为了解决页面之间的跨域通信,大家煞费苦心,研究了各种跨域方案。之前也有小网同学分享过一篇“跨域,不再纠结” 开始照着尝试时还是有些不够明白的地方,深入了解之后,这里给大家补充一点更具体的做法。
先来看看哪些情况下才存在跨域的问题:
编号 | URL | 说明 | 是否允许通信 |
1 | http://www.a.com/a.jshttp://www.a.com/b.js | 同一域名下 | 允许 |
2 | http://www.a.com/lab/a.jshttp://www.a.com/script/b.js | 同一域名下不同文件夹 | 允许 |
3 | http://www.a.com:8000/a.jshttp://www.a.com/b.js | 同一域名,不同端口 | 不允许 |
4 | http://www.a.com/a.jshttps://www.a.com/b.js | 同一域名,不同协议 | 不允许 |
5 | http://www.a.com/a.jshttp://70.32.92.74/b.js | 域名和域名对应ip | 不允许 |
6 | http://www.a.com/a.jshttp://script.a.com/b.js | 主域相同,子域不同 | 不允许 |
7 | http://www.a.com/a.jshttp://a.com/b.js | 同一域名,不同二级域名(同上) | 不允许(cookie这种情况下也不允许访问) |
8 | http://www.a.com/a.jshttp://www.b.com/b.js | 不同域名 | 不允许 |
b.html的高度,使iframe不要出现滚动条。我们都知道跨域了,a.html是没办法直接读取到b.html的高度的,b.html也没办法把自 己的高度告诉a.html。 直接说可以用代理页面的方法搞定这个问题吧,但是怎么代理法,先来看下面这张图:
图1
b.html与a.html是不能直接通信的。我们可以在b.html下面再iframe内嵌一个proxy.html页面,因为这个页面是放在 a.com下面的,与a.html同域,所以它其实是可以和a.html直接通信的,假如a.html里面有定义一个方法_callback,在 proxy.html可以直接top._callback()调用它。但是b.html本身和proxy.html也是不能直接通信的,所谓代理页面的桥 梁作用怎么实现呢? b.html内嵌proxy.html是通过一段类似下面这样的代码: <iframe
id=”proxy” src=”a.com/proxy.html” name=”proxy” frameborder=”0″ width=”0″ height=”0″></iframe> 这个iframe的src属性b.html是有权限控制的。如果它把src设置成a.com/proxy.html?args=XXX,也就是给url加 一个查询字符串,proxy.html内的js是可以读取到的。对的,这个url的查询字符串就是b.html和proxy.html之间通信的桥梁,美 中不足的是每次通信都要重写一次url造成一次网络请求,这有时会对服务器及页面的运行效率产生很大的影响。同时由于参数是通过url来传递的,会有长度
和数据类型的限制,搜集的资料显示:
IE浏览器对URL的长度现限制为2048字节。
360极速浏览器对URL的长度限制为2118字节。
Firefox(Browser)对URL的长度限制为65536字节。
Safari(Browser)对URL的长度限制为80000字节。
Opera(Browser)对URL的长度限制为190000字节。
Google(chrome)对URL的长度限制为8182字节。
上面的方法,通过迂回战术实现了b.html跟a.html通信,但是倒过来,a.html怎么跟b.html通信呢?嵌入在b.html里面的 proxy.html可以用top快速的联系上a.html,但是要想让a.html找到proxy.html就不容易了,夹在中间的 b.html生生把它们分开了,a.html没法让b.html去找到proxy.html然后返回给它。只能采用更迂回的战术了。 顺着前面b.html到a.html的通信过程,逆向的想一下,虽然a.html没有办法主动找到proxy.html,但是proxy.html可以反
过来告诉a.html它在哪里: 在proxy.html加这么一段脚本:
性,就是页面在同一个浏览器窗口(标签页)中跳转时,它一直存在而且值不会改变。比如我们在a.html中设置了window.name=”a”,然后 location.href=”http://b.com/b.html”跳转 后,b.html可以读取window.name的值为”a”;而且window.name的值长度一般可以到达2M,ie和firefox甚至可以达到
32M,这样的存储容量,足够利用起来做跨域的数据传递了。好吧,我们现在要做的就是当proxy.html拿到a.html发送过来的数据后把这个数据 写入window.name中,然后跳转到b.com下面的代理页面,我们这里假设是bproxy.html。bproxy.html读取到 window.name值后,通知给它父页面b.html就简单了。我们再来看这个过程可以用图大概示意一下:
图2
图例中绿色的双向箭头表示可以通信,橙色的双向箭头表示不能直接通信。 最后我们简单看一下双向通信的实测效果:
图3
b.html每次加载的时候都先给a.html发一个”连接请求”,让a.html可以找到proxy.html。所以页面第一次加载的时候会产生三个请求:
图4
每次b.html向a.html发送消息的时候会产生一个请求:
图5
每次a.html向b.html发送消息的时候会产生两个请求,其中一个是a.com/proxy.html向b.com/bproxy.html跳转产生的,另一个是b.html重新向a.html发起“连接请求”时产生的:
图6
最后简单看一下实测的几个测试页面代码: 代码片段一,a.com/a.html:
正是为了满足一些合理的、不同站点之间的内容能在浏览器端进行交互的需求而设计的。利用postMessage API实现跨域通信非常简单,我们直接看一下实例的代码: 代码片段五,A.com/a.html:
图7
但是为了覆盖ie6等低版本浏览器,我们完整的方案里面还是要包含一下兼容代码,就是最开始介绍的代理页面的方法了,但必须是以postMessage为主,这样即便最后会有某些浏览器因为这种通信产生一些网络请求,比例也是非常低的了。
相关文章推荐
- 【JavsScript】父子页面之间跨域通信的方法
- 父子页面之间跨域通信的方法
- (转)父子页面之间跨域通信的方法
- 【JavaScript】父子页面之间跨域通信的方法
- 父子页面之间跨域通信的方法
- 父子页面之间跨域通信的方法
- 父子页面之间跨域通信的方法(转)
- [转]父子页面之间跨域通信的方法
- 父子页面之间跨域通信的方法
- 嵌套iframe下父子页面之间的通信(跨域及同域的分析)
- JavaScript:父子页面(iframe)之间通信实例
- 从跨域和同域两个角度实现多页面之间的通信
- vue开发:vue2.0父子组件及非父子组件之间的通信方法
- question:applet与浏览器通信,同页面内applet之间通信,jsp控制applet异步运行,servlet启动applet方法 jsp获取applet返回值
- js 的 iframe 父子页面通信的简单方法
- iframe 父子页面之间的js函数调用方法
- vue2.0父子组件及非父子组件之间的通信方法
- 嵌套iframe下父子页面之间的通信
- 嵌套iframe下父子页面之间的通信
- 六)iframe 及父子页面之间获取元素、方法调用