实现跨域通信(跨文档消息传输)的几种方法(crossMessageEvent.js)

标签: 跨域 | 发表时间:2014-12-27 22:18 | 作者:kidsama
出处:http://segmentfault.com/blogs

最近两天为实现一个跨域通信的问题,对这个问题进行了相关的学习,心得一二,在此分享。

window.postMessage()方法

HTML5给我们带来了安全的跨域通信接口,即window.postMessage()方法。它方法原型是:

  window.postMessage(msg, domain);

该方法的浏览器支持情况:E8+, FF3+, Chrome, Safari,且在IE下,msg参数必须是string,不能是object.由此可见,我们只要考虑IE6,IE7下的跨域实现。

一、方案一

使用window.postMessage + window.opener实现,该方式是利用IE6,7 opener hack的方式实现跨域,可以算一个安全漏洞。

实现方式:

  • 1、www.a.com/a.html 和 www.b.com/b.html,b.html被a.html嵌套在iframe里面。
  • 2、首先两个页面各设置目标通信页面的opener = {};opener对象可包含一个方法,这样当前页面可以直接调用目标页面的opener内的方法,并传递参数。

www.a.com/a.html

  var otherWindow = document.getElementById("ifr_a").contentWindow; //ifr_a为嵌套b.html的iframe ID
otherWindow.opener={
    postMessage:function(str){
        alert(str);
    }
}

www.b.com/b.html

  parent.opener={
    postMessage:function(str){
        alert(str);
    }
}

发送消息:

  window.opener.postMessage(message);

这样目标页面就能收到消息了。

我做了一下JS的封装,大家可以直接下载使用:crossMessageEvent_opener.js

下载:crossMessageEvent_opener.js

  • 1、a.html和b.html分别引用该JS* 2、分别进行初始化CrossMessageEvent.init(otherWindow); //otherWindow 为目标窗口的window对象* 3、发送消息CrossMessageEvent.postMessage(otherWindow, message, targetOrigin);

    otherWindow:为目标窗口的window对象
    message:消息内容,可以是object
    targetOrigin:目标窗口的域 [可选]

  • 4、添加消息接收的监听

    CrossMessageEvent.receiveMessage(funciton(event){
    alert(event.data); //event.data为message的内容
    });

该方法的优点:

不需要使用代理页面,简单直接。

该方法的缺点:

只要打过微软的安全补丁.kb2497640就不能用了。

二、方案二

使用Iframe来实现跨域。

理论上使用Iframe的原则:

  • 1.当前层级中的任何Window都可以获取其他Window(iframe也是一个Window)* 2.只有同域Window才可以互相操作* 3.当前层级下的任何Window可以设置其他Window的location,即使是不同的域* 4.当你改变url的hashtag(url #后面的字符串)时,页面不会刷新

实现方式:

  • 1、www.a.com/a.html 和 www.b.com/b.html 及www.a.com/a_proxy.html 和 www.b.com/b_proxy.html* 2、如图所示

各个页面的iframe嵌套关系.png

图例中表明了各个页面的iframe嵌套关系。

b.html向a.html发送消息:

  • (图中的箭头1)b.html嵌套一个a_proxy.html代理页面,通过将消息值传递到hashtag或iframe的window.name中进行保存* (图中的箭头2)a_proxy.html接收到消息值后,向上找到自己同域的a.html(parent.parent.方法),调用a.html中的一个方法,将消息用参数传递过去。* 理论上来说,由于a_proxy.html和a.html同域,所以a_proxy.html可以操作a.html。在IE6和IE7下测试通过。

a.html向b.html发送消息:

  • (图中的箭头3)a.html嵌套一个b.html,并嵌套一个b_proxy.html,将消息能过window.name或hashtag的方法给到b_proxy.html。* (图中的箭头4)b_proxy.html接收到消息后,通过parent.frames['b_ifr'].方法,并将消息通过参数传递过去。* parent.frames['b_ifr']为b.html的iframe的窗口句柄。* 理论上parent.frames['b_ifr']和b_proxy.html是同域下的window互相操作。在IE7下测试通过,有的IE6下也能通过,但是大部份IE6下测试不通过,提示权限不足!

PS:我同事糖饼就是用这个方法实现的: http://www.planeart.cn/?p=1620

三、方案三:crossMessageEvent.js【推荐】

使用window.postMessage + hashtag轮询实现

实现方式:

通过改变目标窗口的location.hash值,目标页面进行轮询监听hash变化,来进行消息传递。

该种方式,不需要使用代理页面,可以避免iframe跨域带来的不稳定因素,由于需要一个定时器,效率稍低,但对于不是频繁的消息传递还是够用的。

crossMessageEvent.js就是采用这种方式来实现ie6,ie7的跨域消息传递。

crossMessageEvent.js使用:

crossMessageEvent.js下载: crossMessageEvent

  • 1、a.html和b.html分别引用该JS* 2、发送消息

    CrossMessageEvent.postMessage(otherWindow, message, targetOrigin);

    otherWindow:为目标窗口的window对象
    message:消息内容,可以是object
    targetOrigin:目标窗口的域 [可选]

  • 3、添加消息接收的监听

    CrossMessageEvent.receiveMessage(funciton(event){
    alert(event.data); //event.data为message的内容
    });

该方法的缺点是,会改变URL的hash,导致历史记录发生相应的变化,影响浏览器的前进和后退,且数据暴露在URL。

四、方案四

b页面给a页面发送消息采用方案二中的iframe代理方式。
a页面给b页面发送消息采用hash轮询的方式。
这样可以避免b页面将顶级页面的URL中的hash改变。

———————————————————

参考文献:

http://www.cnblogs.com/xueduanyang/archive/2011/08/23/2150090.html

http://www.alloyteam.com/2012/08/lightweight-solution-for-an-iframe-cross-domain-communication/

http://www.planeart.cn/?p=1620


via Just Jason's Blog

相关 [通信 文档 消息] 推荐:

实现跨域通信(跨文档消息传输)的几种方法(crossMessageEvent.js)

- - SegmentFault 最新的文章
最近两天为实现一个跨域通信的问题,对这个问题进行了相关的学习,心得一二,在此分享. window.postMessage()方法. HTML5给我们带来了安全的跨域通信接口,即window.postMessage()方法. 该方法的浏览器支持情况:E8+, FF3+, Chrome, Safari,且在IE下,msg参数必须是string,不能是object.由此可见,我们只要考虑IE6,IE7下的跨域实现.

HTML5 web通信(跨文档通信/通道通信)简介

- - 张鑫旭-鑫空间-鑫生活
本文地址: http://www.zhangxinxu.com/wordpress/?p=2229. web通信(洋名:web messaging)是一种文档中独立的浏览上下文间的DOM不会被恶意的跨域脚本暴露数据分享方式. 得得得,术语啊什么的,比看到凤姐还头疼. web通信是一种数据分享方式(有屁话之嫌);.

iPhone 13或支持LEO卫星通信 没有4G/5G也能发消息打电话

- - 威锋网-首页-最新RSS订阅
据分析师郭明錤称,iPhone 13将支持低地球轨道(LEO)卫星通信连接,允许用户在没有4G或5G覆盖的地区打电话和发送消息. 在一份致投资者的报告中,郭解释说,‌iPhone 13‌系列将配备能够连接到LEO卫星的硬件. 如果启用相关软件功能,这将允许‌iPhone 13‌用户无需4G或5G蜂窝连接即可打电话和发送消息.

消息两则

- 藏书人 - 李志官方博客
1,经过深思熟虑,我放弃了十月份做个人小巡演的计划,全心全意投入跨年音乐会的准备工作. 如不出意外,12月31日南京见. 2,如果不出意外,第六张专辑会在十一之前发布. 经过深思熟虑,我决定不做实体,直接放到官网提供下载,能者多劳,愿者给钱. 3,当然对我而言,意外是常态.

周一消息树

- 水御龙神 - 1416 教室
每一个光鲜的封面,都饱含美术编辑的”血泪“和杂志主编的“阴谋”——今天的消息树让我们将掀开封面往里瞅瞅. 最新一期的美国新闻周刊封面,实在让人有点儿难以置信. 优雅的戴安娜王妃突然出现在二十一世纪的街头,旁边是她的儿媳妇Kate,但仔细看,她却不是当年的王妃,变老了,变丑了——这是新闻周刊编辑们想象中的一个五十岁的女人的样子.

HTML5 & CSS3 研究文档

- Kings - 幸福收藏夹
已经说了好久,一直没把这个文件夹分享出来. 这是我去年第四季度里做的,里面有 11 一个文档. 包括 HTML5 中最主要的 JS API 文档,还有 CSS3 中两个比较难的属性. 主要还停留在纯 API 层面上的研究,没有深入到应用中去. 不过,当做工具来使用,和入门文档,还是不错的. 特别是其中的 HTML5 JS API 文档.

Twitter API中文文档

- Jacob - 月光博客
  目前的国内的微博客很多,不少微博客都提供Open API,然而,很多微博提供的API和Twitter的API有一些或多或少的差别,调用格式上并不完全相同.   我建议所有提供API的微博客系统,都将各自的API统一为Twitter的API调用格式,例如目前较有影响的开源微博系统StatusNet(Laconica)的API格式就完全兼容Twitter,这种统一API对于开发者和用户都有很大的好处.

Underscore.js Version (1.2.3) 中文文档

- - WEB前端开发
Underscore 一个非常实用的JavaScript库,提供许多编程功能的支持,就像你期望 Prototype.js (或者 Ruby), 有这些功能且不扩展任何JavaScript的原生对象. 有函数式编程的风格,还支持链式调用. 主要涉及对Collection、Object、Array、Function的操作,还有一些实用方法.