`
天梯梦
  • 浏览: 13747386 次
  • 性别: Icon_minigender_2
  • 来自: 洛杉矶
社区版块
存档分类
最新评论

iframe跨域通信的通用解决方案-第二弹!(终极解决方案)

 
阅读更多

一年前,我发过一篇关于跨文档通信方案的文章《iframe跨域通信的通用解决方案》,提供了一种基于创建iframe与轮询window.name的方案。

 

一年后,很高兴地带来彻底改造的新版本。实际上新方案已经用了很久了,一直没有时间抽象出来,最近终于挤时间分享出来了!~

 

回望过去

第一版的方案还是有不少问题,这里统一回复与总结一下。第一次使用MessengerJS的同学,可以直接跳到下面的“新版使用”小节。

 

无法使用的反馈

第一版方案,在一定程度上可以解决iframe通信的问题,但从大家的反馈上看,还是存在一些不足。这里列举一下评论里反馈的问题:

 

  • HTTP与HTTPS,无法通信
  • IE6在某些设置下,无法通信
  • js设置document.domain后,无法通信
*上述问题本人并未全部确认

 

性能有损

第一版方案,需要在内层的iframe中创建两个iframe,并且需要跑定时器轮询window.name,其性能必然有所损耗,更不要说在IE6/7下执行这样的操作。如果父窗口要与两个iframe通信,那么性能的问题也会成倍增长。

 

API不一致

第一版方案,为父窗口和iframe提供了不同的API。这样的设计并不友好,使用者应该把每个窗口对象统一对待。

 

多iframe通信?

多个iframe无法直接通信,需要父窗口中转才行。

 

问题新版都解决了?

那是必须的,上述问题全部得以解决,更重要的是,代码量还减少了50%+!

 

新方案原理概述

概念上,方案的理念还是使用“信使”概念,即 Messenger。

 

对于现代浏览器,postMessage API还是无可撼动的。IE6/7下,使用的是一个被认为是bug或安全漏洞的特性,即navigator对象在父窗口和iframe之间是共享的。 基于这一点,我们可以在父窗口中,在navigator对象上注册一个消息回调函数;在iframe中,调用navigator上的这个函数并传入参数。 此时可看作,iframe往父窗口的一个函数传递了一个参数,并在父窗口的上下文中执行了,那么就相当于iframe向父窗口发送了一条消息。反之亦然。

 

原理就是这么简单(这次我连图都不用画了),好处也是很明显的:

 

  • 该方案不依赖浏览器的各项设计,不受设置影响,同时完美支持HTTPS
  • 不用创建多余iframe,基于接口调用,不需要轮询,性能大幅提升
  • 良好的接口封装,所有窗口对象统一对待
  • 多iframe也不怕,navigator对象的共享,让iframe之间直接通信成为可能

 

关于安全性

有些同学认为上述方案存在安全风险,也有在wuyun反馈这类问题,但微软并没有去修改。

 

其实并不用担心,这里做个简单说明:

 

我们只将消息回调函数注册在navigator对象上,虽然任何引入的脚本或页面,都可以向navigator上发消息,但这其实和 postMessage不限域的情况并无差异。这里对开发者的建议是,传递消息使用JSON String的形式,使用一个字段做消息有效性的验证。如果怕一个固定值(如项目名)不安全,可以使用一个简单的加密算法,并对业务脚本进行压缩混淆,此 时的安全风险可以降到最低。

 

好处说完了,怎么用?

  1. 在需要通信的文档中(父窗口和iframe们), 都确保引入MessengerJS
  2. 每一个文档(document), 都需要自己的Messenger与其他文档通信. 即每一个window对象都对应着一个, 且仅有一个Messenger对象, 该Messenger对象会负责当前window的所有通信任务. 每个Messenger对象都需要唯一的名字, 这样它们才可以知道跟谁通信.
    // 父窗口中 - 初始化Messenger对象
    var messenger = new Messenger('Parent');
     
    // iframe中 - 初始化Messenger对象
    var messenger = new Messenger('iframe1');
     
    // 多个iframe, 使用不同的名字
    var messenger = new Messenger('iframe2');
     
  3. 在发送消息前, 确保目标文档已经监听了消息事件.
    // iframe中 - 监听消息
    // 回调函数按照监听的顺序执行
    messenger.listen(function(msg){
        alert("收到消息: " + msg);
    });
     
  4. 父窗口想给iframe发消息, 它怎么知道iframe的存在呢? 添加一个消息对象吧.
    // 父窗口中 - 添加消息对象, 明确告诉父窗口iframe的window引用与名字
    messenger.addTarget(iframe1.contentWindow, 'iframe1');
     
    // 父窗口中 - 可以添加多个消息对象
    messenger.addTarget(iframe2.contentWindow, 'iframe2');
     
  5. 一切ready, 发消息吧~ 发送消息有两种方式. (以父窗口向iframe发消息为例)
    // 父窗口中 - 向单个iframe发消息
    messenger.targets['iframe1'].send(msg1);
    messenger.targets['iframe2'].send(msg2);
     
    // 父窗口中 - 向所有目标iframe广播消息
    messenger.send(msg);
     
  6. 现在看到iframe收到消息的alert提示了吗?

 

更多

Demo: http://biqing.github.io/labs/messenger/parent.html

项目主页:http://biqing.github.io/MessengerJS/

欢迎反馈,使用中遇到问题一定要告诉我哟!

 

原文:http://www.alloyteam.com/2013/11/the-second-version-universal-solution-iframe-cross-domain-communication/

分享到:
评论
3 楼 wjh_penglei 2016-02-26  
  
谢谢侬
2 楼 天梯梦 2015-01-27  
hzy1934 写道


楼主解决了个大问题!感谢!


不客气,有帮助就好!
1 楼 hzy1934 2015-01-26  


楼主解决了个大问题!感谢!

相关推荐

    iframe跨域通信解决方法

    ### iframe跨域通信解决方法 在现代Web开发中,跨域问题经常出现并困扰着开发者。尤其是在使用`iframe`嵌入不同源的内容时,主页面往往无法直接与`iframe`内的内容进行交互,这就需要一种解决方案来实现跨文档消息...

    iframe跨域解决方案

    综上所述,`iframe`跨域解决方案主要包括`postMessage`通信、`window.name`数据传递以及`CORS`策略。在实际应用中,开发者应根据具体需求和安全考虑,选择合适的跨域策略。同时,需要注意的是,虽然这些方法能突破...

    解决JS跨域访问IFrame的解决方案

    "解决JS跨域访问IFrame的解决方案"这一主题关注的就是如何克服这个限制,使得在JSP页面中嵌入的跨域IFrame能够正常通信。下面我们将详细探讨这个问题以及可能的解决方案。 首先,理解同源策略是关键。同源策略是...

    完美解决iframe跨域问题

    **二、iframe跨域的解决方案** 1. **使用`window.postMessage`**:这是一种现代浏览器支持的跨域通信方式,通过向`window`对象发送消息,可以在不同源的iframe之间传递数据。发送端使用`postMessage(data, ...

    单点登录跨域iframe互相通信方案.zip

    该压缩包文件"单点登录跨域iframe互相通信方案.zip"提供了一种解决方案,可能包含以下关键知识点: 1. **OAuth 2.0或SAML协议**:单点登录通常基于OAuth 2.0或Security Assertion Markup Language (SAML)等标准协议...

    iframe 跨域解决方法

    总的来说,`iframe`跨域问题的解决方案依赖于你的具体需求和目标页面的可控程度。理解并正确使用上述方法,可以有效地解决跨域限制,实现`iframe`间的通信。在实际项目中,务必确保遵循最佳实践,同时注意安全性和...

    MessengerJS-master(iframe跨域通信)

    MessengerJS-master(iframe跨域通信) MessengerJS-master(iframe跨域通信)

    iframe跨域常用问题和iframe页面自适应

    在网页开发中,`iframe`...总结,理解和掌握`iframe`的跨域解决方案以及自适应策略,对于开发高效且用户体验良好的Web应用至关重要。在实际应用中,还需要注意安全性、性能优化等问题,以提供更优质的网页服务。

    iframe跨域通信--html5.postmessage

    总的来说,`iframe`跨域通信和`postMessage`是现代Web开发中解决跨域问题的重要工具,它提高了用户体验,增强了网页间的交互能力,同时也带来了安全性和灵活性的提升。理解和掌握这一技术对于开发者来说至关重要,...

    js跨域解决方案

    4. **IFrame跨域通信**:利用`window.postMessage`方法,可以在属于不同源的两个IFrame之间进行通信。这种方法适用于页面嵌套场景,但不适用于跨域API调用。 5. **WebSocket跨域**:WebSocket协议本身支持跨域,...

    谷歌跨域插件Access-Control-Allow-Origin

    5. 兼容性问题:需要注意的是,不是所有浏览器都支持相同的跨域解决方案,因此在开发跨平台应用时,需要考虑其他浏览器的兼容性,如Firefox、Edge等。 总的来说,谷歌跨域插件Access-Control-Allow-Origin是开发...

    跨域的解决方案有多重JSONP、Flash、Iframe等,当然还有CORS(跨域资源共享,Cross-Origin Resource Sharing)

    然而,随着Web应用的发展,跨域数据交互的需求日益增多,因此催生了一系列跨域解决方案,包括JSONP、Flash、Iframe以及CORS(跨域资源共享,Cross-Origin Resource Sharing)。 首先,JSONP(JSON with Padding)是...

    iframe 跨域访问session

    `iframe` 跨域访问`session`正是为了解决这一问题。 首先,让我们了解一下`session`和`cookie`的关系。`session`通常用于存储用户登录状态等临时信息,而`cookie`则作为`session` ID的载体在客户端和服务器之间传递...

    JQuery跨域访问解决方案

    JQuery的跨域解决方案主要依赖于JSONP(JSON with Padding)技术。JSONP是一种绕过同源策略的方式,它利用HTML中的`<script>`标签没有同源策略限制的特点。当jQuery使用`dataType: 'jsonp'`时,它实际上是在做以下几...

    Tomcat跨域请求资源解决方案.zip

    本资料包“Tomcat跨域请求资源解决方案.zip”显然是针对这个问题提供了一个具体的解决方案,主要聚焦于如何在Apache Tomcat服务器上配置以允许跨域请求。 Tomcat是Java Servlet容器,广泛用于部署Java Web应用程序...

    Geoserver跨域问题解决方案

    在IT行业中,尤其是在Web开发领域,跨域问题是一个常见的挑战,尤其当涉及到GIS(地理信息系统)服务时,如Geoserver。Geoserver是一个开源的、基于Java的服务器,用于发布和管理地理空间数据。当从一个源(如浏览器...

    Ajax跨域访问解决方案

    **Ajax跨域访问解决方案** 在Web开发中,Ajax(Asynchronous JavaScript and XML)技术被广泛用于实现页面的异步更新,提升用户体验。然而,由于浏览器的同源策略限制,Ajax请求只能向同源(协议、域名和端口相同)...

    Ajax跨域请求解决方案-JSONP

    然而,Ajax技术在实现动态网页交互时常常需要跨越这个限制,这时就引入了JSONP(JSON with Padding)作为跨域请求的一种解决方案。本文将详细介绍JSONP的工作原理以及如何在ASP.NET网站开发中应用JSONP解决Ajax跨域...

    Javascript跨域访问解决方案

    JavaScript跨域访问解决方案 在Web开发中,JavaScript的同源策略是浏览器为了保障用户安全而实施的一项重要机制。它限制了脚本只能访问与当前页面具有相同协议(如http或https)、主机名和端口号的资源。然而,在...

Global site tag (gtag.js) - Google Analytics