当前位置: 代码迷 >> 综合 >> HTML5 Cross-Document Messaging 跨域(postMessage)
  详细解决方案

HTML5 Cross-Document Messaging 跨域(postMessage)

热度:16   发布时间:2023-12-21 14:06:13.0

前言

出于安全和隐私的原因,Web浏览器会阻止不同域中的文档互相影响; 也就是说,跨站点脚本是不允许的。但很多时候需要跨域操作,因此开发出允许跨域方法document.domain,JSONP,CORS等。这些跨域方式都有一定的局限性,比如我最近遇到一个跨域问题,我在www.A.com域打开一个www.B.com域的网页,需要B网址操作完成后,前端通知A网址。上面这些方法都不能有效地跨越通信。

而这是我查看文档,发现HTML5提供了一种新的跨域方法 称为跨文档通信(cross-document messaging),这是作用于网页之间互相通信与发送信息的功能。使用这个功能,只要获取到网页所在窗口对象的实例,不仅同源(域 + 端口号)的 Web 网页之间可以互相通信,甚至可以实现跨域通信。 要想接收从其他窗口发送来的信息,必须对窗口对象的 message 事件进行监听,其它窗口可以通过 postMessage 方法来传递数据。
这里写图片描述

用法

1.前提A域名使用window.open打开B域名站点。
2.B域名发送一个信息“HI”给”http://www.A.com“。

var targetWindow = window.opener;
targetWindow.postMessage("HI", "http://www.A.com");

3.A域接收消息后,分析是”http://www.B.com“传来的 传回去”I’m fine”,给”http://www.A.com“。

window.addEventListener('message', receiver, false);
function receiver(e) {
    if (e.origin == "http://www.B.com") {if (e.data == "HI") {e.source.postMessage("I'm fine", e.origin);} }
}


发送信息-postMessage

postMessage负责发送信息,向给定窗口发布消息。消息可以是结构化对象。

postMessage(data,origin)方法接受两个参数:

字段 介绍
data 要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js可以实现类似效果。
origin 字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为”*”,这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为”/”。

例子

window.opener.postMessage(“HI”, “http://www.A.com“);
//这样 发送一个“HI”给 A 信息了。


接收事件-message

window新事件message,负责接送信息。通过发布一个message方法来,接听其网站的信息。postMessage(message,targetOrigin [,transfer ])

window.addEventListener(‘message’, function(e){console.log(e)}, false);
//这是一个接收器 接收信息输出。

window.attachEvent(‘message’, function(e){console.log(e)}, false);
//IE9以下使用attachEvent

接收的对象用下面属性。

其中有几个重要属性

字段 介绍
data 接收message传递过来的值,值的类型是字符串形式。
source 发送消息的窗口对象。
origin 发送消息窗口的源(协议+主机+端口号)。

安全性

使用此API需要格外小心,因为这个是开方一个入口,允许大家来发送信息。

因此使用message应该设置好origin属性,以确保允许的域的信息。避免给其他恶意网址来利用攻击。

还有postMessage() 也要设置好origin,这样避免信息未经授权而被其他网站接收。不建议设置(*)

攻击者可以发送大量的消息; 如果接收页面执行昂贵的计算或导致为每个此类消息发送网络流量,则攻击者的消息可能会成倍增加,从而导致拒绝服务攻击。鼓励采用速率限制(每分钟只接受一定数量的消息)以使这种攻击不切实际。

兼容性

Chrome浏览器 64+
Chrome 4+
iOS Safari 3.2+
UC浏览器Android 11.8+
Firefox 3+
IE浏览器(限定) 8+
三星Internet 4+
Opera Mini 全部+
Safari 4+
Edge 12+
Android Browser 2.1 +
Opera 9.5+
来源:caniuse.com

注意事件

1.Cross-Document Messaging适合对窗口来互相传值使用,但如果要做页面跳转会被浏览器安全限制的。(IE浏览器限制不能别其他域来跳转)
2.使用需要清晰知道窗口关系,这样才能正确传递值。

iframe例子

父级页面A


function receiver(e) {
    if (e.origin == "http://www.B.com") {if (e.data == "HI") {e.source.postMessage("I'm fine", e.origin);} }
}try{window.addEventListener('message', receiver, false);
}catch(e){window.attachEvent('message', receiver, false);
}

子级页面B

    window.parent.postMessage("HI", "http://www.A.com");
  相关解决方案