理解 `window.postMessage`:安全地跨源通信

272 阅读2分钟

在web开发中,浏览器的同源策略经常阻碍我们执行跨源请求和操作。但有时,我们确实需要在不同的源之间进行安全的通信。这时,window.postMessage 便派上了用场。

什么是 window.postMessage

window.postMessage 是一个允许不同源之间进行安全通信的方法。它允许你发送消息给其他窗口或iframe,不论这些窗口或iframe是否来自同一源。

如何使用 window.postMessage

发送方可以使用 postMessage 方法发送消息:

otherWindow.postMessage(message, targetOrigin, [transfer]);
  • message: 要发送的消息。这可以是任何可以被克隆的值,例如一个字符串、数字或对象。
  • targetOrigin: 指定消息接收方的源。可以是一个URL的协议、主机和端口。为了安全起见,建议明确指定目标源。如果你确实想发送给任何源,可以使用 '*',但这通常不推荐。
  • transfer (可选): 是一个传输数据的数组。

接收方需要设置一个监听器来接收这些消息:

window.addEventListener('message', (event) => {
    // 你的处理代码
});

安全性如何?

虽然 postMessage 允许跨源通信,但它是设计得非常安全的:

  1. 明确的目标源:发送方必须明确指定消息的目标源。这确保了消息只会发送给预期的接收方。
  2. 源检查:接收方可以检查 event.origin 来确定消息来源,并决定是否处理该消息。
  3. 数据隔离:通过 postMessage 传递的数据必须是可序列化的,这提供了一定程度的数据隔离。

使用场景

  1. Web Workers:Web Workers 运行在与主线程不同的上下文中,因此它们不能直接访问主线程中的对象。使用 postMessage 可以在主线程和 Worker 之间进行通信。
  2. 跨文档通信:例如,一个主页面和一个嵌入的iframe需要交换信息,即使它们来自不同的源。
  3. 浏览器插件与页面交互:例如,插件的 content script 需要与主页面进行通信。

结论

window.postMessage 是一个强大而安全的工具,允许我们跨源或跨上下文进行通信,而不违反浏览器的安全策略。当需要进行此类通信时,确保始终检查消息的来源,并只向预期的接收方发送消息,以保持通信的安全性。