关于window.postMessage的疑问?

新手上路,请多包涵

MDN中这样描述其参数targetOrigin:通过窗口的 origin 属性来指定哪些窗口能接收到消息事件,其值可以是字符串*,表示无限制,也可以是一个URI。我尝试了一下,targetOrigin不生效

我是通过VSCode编写的代码,通过其Live Server插件启动一个本地服务。代码如下

// main.html
<body>
  <h1>Main Window</h1>
  <button id="postMessage">post message</button>
  <iframe src="content.html" id="content_iframe" width="400" height="200"></iframe>

  <script>
    const contentIframe = document.getElementById('content_iframe');
    const button = document.getElementById('postMessage');
    button.addEventListener('click', () => {
      // A
      window.postMessage({ type: 'main', data: 'from main' });
    });

    window.addEventListener('message', e => {
      const { data: { type, data } } = e;
      console.log(`main window received a message. message=${type}, data=${data}`);
    });
  </script>
</body>
// content.html
<body>
  <h1>Content Window</h1>
  <button id="postMessage">post message</button>

  <script>
    const button = document.getElementById('postMessage');
    button.addEventListener('click', () => {
      // B
      window.postMessage({ type: 'content', data: 'from content' });
    });

    window.addEventListener('message', e => {
      const { data: { type, data } } = e;
      console.log(`content window received a message. message=${type}, data=${data}`);
    });
  </script>
</body>

尝试测试以下场景:

  • A处采用window.postMessage,不指定targetOrigin,只有main.html收到消息;
  • A处采用window.postMessage,指定targetOrigin为*,只有main.html收到消息;
  • A处采用contentIframe.contentWindow.postMessage,不指定targetOrigin,只有content.html收到消息;
  • A处采用contentIframe.contentWindow.postMessage,指定targetOrigin为*,只有content.html收到消息;
  • B处采用window.postMessage,不指定targetOrigin,只有content.html收到消息;
  • B处采用window.postMessage,指定targetOrigin为*,只有content.html收到消息;
  • B处采用parent.potMessage,不指定targetOrigin,只有main.html收到消息;
  • B处采用parent.potMessage,指定targetOrigin为*,只有main.html收到消息;

经过以上测试,我总结为:通过window.postMessage实现两个窗口的通信,不管是否跨源,想要给对方发消息就必须要持有对方的引用,但我想不明白如何去总结targetOrigin,它貌似没什么作用

阅读 825
2 个回答

可以看看它的英文描述:

Specifies the origin the recipient window must have in order to receive the event.

指定接收消息的window的origin以便接收事件。

应该是这么理解,targetOrigin 是为了确保真的发送过去消息的时候,发对了“人”。假设你的content_iframe突然跳到其他页面C去了,然后你的main.html还往它发消息的时候,targetOrigin保证了其他页面C不会接收到这个事件。为了安全~

window.postMessage 是一个Web API,它允许来自不同源的页面间安全地传递消息。这个API在处理跨源通信(cross-origin communication)时非常有用,比如当你需要从iframe中向父页面发送消息,或者在不同的iframe之间进行通信时。

使用 window.postMessage 时,通常涉及到两个步骤:

  1. 发送消息:使用 postMessage 方法发送消息到另一个窗口(可以是同源的也可以是不同源的)。这个方法接受两个参数,第一个是要发送的消息,第二个是目标窗口的源(origin),如果目标窗口是同源的,这个参数可以省略。

    // 发送消息
    var targetOrigin = "http://example.com";
    var message = "Hello there!";
    window.postMessage(message, targetOrigin);
  2. 接收消息:在目标窗口监听 message 事件来接收消息。你可以在事件监听器中检查消息的来源和内容,以确保消息是预期的。

    // 接收消息
    window.addEventListener("message", function(event) {
        // 检查消息的来源
        if (event.origin !== "http://example.com") {
            return; // 只接收来自特定源的消息
        }
    
        // 处理消息
        console.log("Received message:", event.data);
    }, false);

使用 window.postMessage 时的一些注意事项:

  • 安全性:当你使用 postMessage 时,确保检查 event.origin 属性,以确保消息来自可信的源。这可以防止潜在的跨站脚本攻击(XSS)。
  • 数据格式postMessage 方法可以接受字符串或可以被结构化克隆算法(structured clone algorithm)处理的对象。这意味着你可以发送复杂数据结构,而不仅仅是字符串。
  • 同源策略:如果发送和接收消息的窗口是同源的,那么 event.origin 属性将返回一个空字符串。在这种情况下,你可能需要依赖其他方式来验证消息的来源。
  • 浏览器兼容性window.postMessage 在现代浏览器中得到了很好的支持,但在一些旧的浏览器版本中可能不可用。

如果你有关于 window.postMessage 的具体疑问或者遇到了问题,可以详细描述你的情况,我会尽力帮助你解决。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏