百科狗-知识改变命运!
--

html5 跨文档通讯 - html5 详细教程

是丫丫呀1年前 (2023-11-21)阅读数 14#技术干货
文章标签消息

html5 跨文档通讯

版本:HTML5

对窗口对象的message事件进行监听,使用window对象的postMessage()方法向其他窗口发送消息。

跨文档消息传送(cross-document messaging),简称XDM,指的是来自不同域的页面间传递消息。

html5 跨文档通讯 - html5 详细教程

XDM的核心是postMessage()方法。目的:向另一个地方传递数据。对于XDM而言,“另一个地方”指的是包含在当前页面中的元素,或者由当前页面弹出的窗口。

postMessage()方法接收两个参数:一条消息和一个表示消息接收方来自哪个域的字符串。第二个参数对保障安全通信非常重要,可以防止浏览器把消息发送到不安全的地方。

接收到XDM消息时,会触发window对象的message事件。这个事件是以异步形式触发的,因此从发送消息到接受消息(触发接受窗口的message事件)可能要经过一段时间的延迟。

有了XDM,包含的页面可以确保自身不受恶意内容的侵扰,因为它只通过XDM为嵌入的框架通信。而XDM也可以来自相同域的页面间使用。

如果要实现从一个页面向到另一个页面传递消息,使用html5的API就可以实现。postMessage()就是用来试下跨文档消息传递的,不过这个API有局限,只能新开的页面传递消息(内嵌也可以)。

浏览器支持

Internet Explorer 8 以上版本支持

postMessage()

otherWindow.postMessage(message, targetOrigin, [transfer]);
  • otherWindow是目标窗口的引用,在当前场景下就是iframe.contentWindow;
  • message是发送的消息,在Gecko 6.0之前,消息必须是字符串,而之后的版本可以做到直接发送对象而无需自己进行序列化。
  • targetOrigin表示设定目标窗口的origin,其值可以是字符串"*"(表示无限制)或者一个URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配targetOrigin提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。对于保密性的数据,设置目标窗口origin非常重要。
  • transfer可选参数,是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权。

当postMessage()被调用的时,一个消息事件就会被分发到目标窗口上。该接口有一个message事件,该事件有几个重要的属性:

  • data:顾名思义,是传递来的message。
  • source:发送消息的窗口对象。
  • origin:发送消息窗口的源(协议+主机+端口号)。
  • otherwindow为要发送窗口 对象的引用,可以通过window.open()方法返回该对象,或通过对window.frames数组指定序号(index)或名字的方式来返回单个 frame所属性的窗口对象。

    那么,当iframe初始化后,可以通过下面代码获取到iframe的引用并发送消息:

    // 注意这里不是要获取iframe的dom引用,而是iframe window的引用
    const iframe = document.getElementById('myIFrame').contentWindow;
    iframe.postMessage('hello world', 'https://www.qq344225443/cn');
    

    在iframe中,通过下面代码即可接收到消息。

    window.addEventListener('message', msgHandler, false);
    

    在接收时,可以根据需要,对消息来源origin做一下过滤,避免接收到非法域名的消息导致的xss攻击。

    实例

     跨文档消息传输示例主文档  
                 
                 
        $(function() {   
           // 监听message事件。   
           window.addEventListener("message", function(event) {   
               // 忽略指定URL之外的页面发送的消息。   
               if(event.origin != "https://www.qq344225443/cn") return;   
               alert(event.data); // 显示消息。   
           }, false);   
              
           $("#iframeContent").load(function(event) {   
                   // 向子页面发送消息   
               this[0].postMessage("Hello", "https://www.qq344225443/cn/test/");   
           });   
        }); 

    跨域通信示例

    子页面中的代码

     $(function() {   
           window.addEventListener("message", function(event) {   
               if(event.origin != "https://www.baikegou.com") return;   
               $("#console").append(event.origin).append("传来的消息:").append(event.data);   
                       // 向主页面发送消息。   
               event.source.postMessage("Hello, there is :" + this.location, event.origin);   
           }, false);   
        }); 

    这是iframe中的内容。

    • 通过对window对象的message事件进行监听,可以接收消息。
    • 通过访问message事件的origin属性,可以获取消息的发送源。注意:发送源与网站的URL地址不是一个概念,发送源只包括域名与 端口号,为了不接收其他源恶意发送过来的消息,最好对发送源做检查。
    • 通过访问message事件的data属性,可以取得消息内容(可以是任何JavaScript对象,使用JSON)。
    • 使用postMessage()方法发送消息。
    • 通过访问message事件的source属性,可以获取消息发送源的窗口的代理对象。

    一个页面内嵌另一个页面

    // index.jsp页面(源页面)
    
    
    // 跨域发送数据到目标源
    window.onload = function () 
    {
        document.getElementsByTagName("iframe")[0].contentWindow.postMessage({name: 'wujiang'}, "http://localhost:8090");
    }
    // 监听目标源发送过来的数据
    window.addEventListener('message', function (e)
    {
        console.log('http://localhost:8090/a.ftl ===> http://localhost:8080/index.jsp');
        console.log(e);
    }) 
    // a.ftl页面(目标页面)
    // 监听其他窗口是否发送数据
    if (window.addEventListener) 
    {
    window.addEventListener('message', function (e) {
        if (e.origin !== 'http://localhost:8080') {
    	return
        }
        console.log('http://localhost:8080/index.jsp ===> http://localhost:8090/a.ftl')
        // 打印数据
        console.log(e)
        // 回传数据
        e.source.postMessage('hello wujiang', e.origin)
    }, false)
    } else if (window.attachEvent) {
    window.attachEvent('onmessage', function (e) {
        if (e.origin !== 'http://localhost:8080') {
    	return
        }
        console.log('http://localhost:8080/index.jsp ===> http://localhost:8090/a.ftl')
        // 打印数据
        console.log(e)
        // 回传数据
        e.source.postMessage('hello wujiang', e.origin)
    }, false)
    } 
    • data:发送的数据
    • origin:源IP地址
    • source:源窗口,可以通过source返回数据到源窗口

    一个页面打开另一个页面

    // 打开一个新窗口
    var newWin = window.open('http://localhost:8090/a');
    // 向新窗口发送数据
    setTimeout(function () {
        console.log('http://localhost:8080/a.jsp ===> http://localhost:8090/a.ftl');
        newWin.postMessage({name: 'wujiang'}, 'http://localhost:8090');
    }, 1000);
    

    鹏仔微信 15129739599 鹏仔QQ344225443 鹏仔前端 pjxi.com 共享博客 sharedbk.com

    免责声明:我们致力于保护作者版权,注重分享,当前被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理!邮箱:344225443@qq.com)

    图片声明:本站部分配图来自网络。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    内容声明:本文中引用的各种信息及资料(包括但不限于文字、数据、图表及超链接等)均来源于该信息及资料的相关主体(包括但不限于公司、媒体、协会等机构)的官方网站或公开发表的信息。部分内容参考包括:(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供参考使用,不准确地方联系删除处理!本站为非盈利性质站点,本着为中国教育事业出一份力,发布内容不收取任何费用也不接任何广告!)