必威体育Betway必威体育官网
当前位置:首页 > IT技术

前端 postMessage

时间:2019-06-09 21:45:14来源:IT技术作者:seo实验室小编阅读:73次「手机版」
 

postmessage

window.postmessage() 方法可以安全地实现跨域通信和页面间数据通信。

postMessage 可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 页面与嵌套的 iframe 消息传递
  • 多窗口之间消息传递

想要使用 postMessage 实现跨域和页面间数据通信,只要记住 window 提供的 postMessage 方法和 message 事件就ok了。

语法:

otherWindow.postMessage(message, targetOrigin, [transfer]);

otherWindow

其他窗口的一个引用,比如 iframe 的 contentwindow 属性、执行 window.open 返回的窗口对象、或者是命名过或数值索引的 window.frames。

message

要发送的数据。它将会被结构化克隆算法序列化,所以无需自己序列化(部分低版本浏览器只支持字符串,所以发送的数据最好用JSON.stringify() 序列化)。

targetOrigin

通过 targetOrigin 属性来指定哪些窗口能接收到消息事件,其值可以是字符串“*”(表示无限制)或者一个 URI(如果要指定和当前窗口同源的话可设置为"/")。在发送消息的时候,如果目标窗口的协议主机地址或端口号这三者的任意一项不匹配 targetOrigin 提供的值,那么消息就不会发送。

The dispatched event

执行如下代码,其他 window 可以监听派遣的 message 获取发送过来的数据:

window.addeventlistener("message", (event)=>{
   var origin = event.origin
   if (origin !== "http://example.org:8080")
     return;
   // ...
}, false);

event 的属性有:

  • data: 从其他 window 传递过来的数据 
  • origin: 调用 postMessage 时,消息发送窗口的 origin。例如:“http://example.com:8080”。
  • source: 对发送消息的窗口对象的引用。可以使用此来在具有不同 origin 的两个窗口之间建立双向数据通信。 

完整案例:

1. 不同 origin 的两个窗口之间建立双向数据通信

/**
* localhost:10002/index页面
**/
// 接收消息
window.addEventListener('message', (e) => {
     console.log(e.data)
})
// 发送消息
const targetWindow = window.open('http://localhost:10001/user');
settimeout(()=>{
     targetWindow.postMessage('来自10002的消息', 'http://localhost:10001')
}, 3000)
/**
* localhost:10001/user页面
**/
window.addEventListener('message', (e) => {
     console.log(e.data)
     if (event.origin !== "http://localhost:10002") 
     return;
     e.source.postMessage('来自10001的消息', e.origin)
})

2. 页面与嵌套的 iframe 消息传递

http://www.domain1.com/a.html

<iframe id="iframe" src="http://www.domain2.com/b.html"></iframe>

<script>
var iframe = document.getelementbyid('iframe');

iframe.onload = function() {
   // 向domain2发送跨域数据
   iframe.contentWindow.postMessage('来自domain1的消息', 'http://www.domain2.com');
};

// 接受domain2返回数据
window.addEventListener('message',(e) => {
    console.log(e.data);
}, false);
</script>

http://www.domain2.com/b.html

<script>
// 接收domain1的数据
window.addEventListener('message',(e) => {
    console.log(e.data);

    if(e.origin !== 'http://www.domain1.com')
    return;

    // 发送消息给domain1
    window.parent.postMessage('来自domain2的消息', e.origin);
}, false);
</script>

安卓平台差异化处理

/* Android 平台 Post Message 消息监听 Hook */
window.Android_handleMessage = message => {
    // Android 使用 base64 编码格式,需要先解码
    let data = decodeURIcomponent(escape(window.atob(message)));
};

安全问题

  1. 如果你不希望从其他网站接收 message,请不要为 message 事件添加任何事件监听器
  2. 如果你确实希望从其他网站接收message,请始终使用 origin 和 source 属性验证发件人的身份。
  3. 当你使用 postMessage 将数据发送到其他窗口时,始终指定精确的目标 origin,而不是 *。

相关阅读

分享到:

栏目导航

推荐阅读

热门阅读