window.postMessage() 方法允许来自一个文档的脚本可以传递文本消息到另一个文档里的脚本,而不用管是否跨域。一个文档里的脚本还是不能调用在其他文档里方法和读取属性,但他们可以用这种消息传递技术来实现安全的通信。

这项技术称为“跨文档消息传递”,又称为“窗口间消息传递”或者“跨域消息传递”。

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 提供的值,那么消息就不会发送。

二、接收消息

如果指定的源匹配的话,那么当调用 postMessage() 方法的时候,在目标窗口的Window对象上就会触发一个 message 事件。

window.addEventListener("message", (event)=>{var origin = event.origin;// 通常,onmessage()事件处理程序应当首先检测其中的origin属性,忽略来自未知源的消息if (origin !== "http://example.org:8080")return;// ...
}, false);

event 的属性有:

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

三、使用场景

当想要在Web页面中嵌入一个来自其他站点的模块或者“gadget”的时候,利用 postMessage() 和 message 事件实现的跨域消息传递是很有用的。

首先 gadget 的开发者可以将 gadget 内容定义在一个 HTML 页面中,它负责监听 message 事件,并将它们分发给对应的 js 函数去处理。然后,嵌入 gadget 的Web页面就可以通过 postMessage() 方法传递消息来和 gadget 进行交互了。

四、完整示例

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;// 发送消息给domain1window.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,而不是 *。

七、兼容性

所有主流浏览器(包括IE8)都支持。

postMessage - 跨域消息传递相关推荐

  1. 浅谈postMessage跨域通信与localStorage实现跨域共享

    我们可能有需要在多个域名之间共用同一个localStorage的需要 一.我们先测试不同域名之间的通信 1.有 child.html 如下,代码中 window.parent.postMessage( ...

  2. iframe跨域消息传递

    window.postMessage() 方法允许来自一个文档的脚本可以传递文本消息到另一个文档里的脚本,而不用管是否跨域.一个文档里的脚本还是不能调用在其他文档里方法和读取属性,但他们可以用这种消息 ...

  3. 使用iframe+postMessage跨域操作和通信

    使用iframe+postMessage跨域操作和通信 场景 1. http://XXX/a.html(自己的)页面要操作http://YYY/b.html(其他域名的) 2. 看了网上很多都是同域名 ...

  4. PostMessage跨域漏洞

    背景 价值: $3000 漏洞原因:postMessage跨域漏洞导致,利用websocket接收用户认证token Hacking Slack using postMessage and WebSo ...

  5. postMessage跨域、跨iframe窗口消息传递

    文章目录 1. 作用 2. 语法 3. 使用 4. 兼容性 5. 应用场景 说起postMessage 可能平时大家也不遇到,但是如果遇到问题了,又想不起它,这里记录下防止后面忘记它. 1. 作用 w ...

  6. window.postMessage - 前端跨域通信

    window.postMessage - 前端跨域通信 window.postMessage() 语法 The dispatched event 安全问题 示例 注意 HTMLIFrameElemen ...

  7. html5 postMessage解决跨域、跨窗口消息传递

    平时做web开发的时候关于消息传递,除了客户端与服务器传值还有几个经常会遇到的问题 1.页面和其打开的新窗口的数据传递 2.多窗口之间消息传递 3.页面与嵌套的iframe消息传递 4.上面三个问题的 ...

  8. html5 postMessage解决跨域、跨窗口消息传递 BY:色拉油啊油

    一些麻烦事儿 平时做web开发的时候关于消息传递,除了客户端与服务器传值还有几个经常会遇到的问题 1.页面和其打开的新窗口的数据传递 2.多窗口之间消息传递 3.页面与嵌套的iframe消息传递 4. ...

  9. ajax跨域请求 html5,HTML5中使用postMessage实现Ajax跨域请求的方法

    由于同源策略的限制,Javascript存在跨域通信的问题,典型的跨域问题有iframe与父级的通信等. 常规的几种解决方法: (1) document.domain+iframe: (2) 动态创建 ...

最新文章

  1. 结构体对齐,结构体深拷贝和浅拷贝
  2. 安卓应用用户数据_Android手机用户注意,你要知道的中国十大安卓应用商店
  3. 使用python 下载_使用python下载大量文件
  4. python中osgeo库使用教程链接
  5. 13--长度最小的子数组
  6. Visual Studio Code 1.42 发布
  7. 复选框 checkbox获取值
  8. Windows 10 20H2 微软MSDN官方正式版ISO镜像下载
  9. kafka 并发数配置过程中踩到的坑 InstanceAlreadyExistsException Error registering AppInfo mbean
  10. sha256 oracle,node如何使用sha256算法?
  11. Java 动态编译基础学习
  12. 怎样开启成功的“数据分析师”职业生涯(R、Python、机器学习、通信和数据可视化、数据直觉)
  13. WPF MVVM设计模式下 相同Xaml绑定不同ViewModel问题
  14. Android EventBus Subscriber class XXXActivity has no public methods called onEvent
  15. Java设计登录界面——GUI
  16. 民事诉讼过程中的一些笔记
  17. 2011互联网泄密事件:***详解账号泄露全过程
  18. 使用eclipse安装python插件_在windows下用eclipse + pydev插件来配置python的开发环境
  19. 给孩子取名时的重点分析
  20. 中国无线可穿戴扬声器行业市场供需与战略研究报告

热门文章

  1. 威联通Kodbox搭建(MariaDB)
  2. Spring Cloud 微服务开发:入门、进阶与源码剖析 —— 1.3 Spring Cloud 与中间件
  3. HashMap的hash碰撞
  4. 茧数SCRM产品介绍系列:智能名片
  5. 简单版留言发布+删除留言
  6. JVM虚拟机原理深入解析,聪明人已经收藏了!
  7. 经典Android开发教程!Android插件化主流框架和实现原理,已拿offer入职
  8. jquery把页面<table>里的内容导出为后缀名为.xlsx的excel
  9. BP神经网络的梯度公式推导(三层结构)
  10. 国科大《高级人工智能》沈老师部分——行为主义笔记