跨源通信的利器:window.open 和 window.postMessage

1,077 阅读2分钟

在前端开发中,跨源通信是一个常见的需求,但同时也是一个安全挑战。幸运的是,现代浏览器提供了一些内置的方法来安全地实现这一功能。在这篇文章中,我们将探讨 window.openwindow.postMessage 方法,以及如何使用它们来实现跨源通信。

window.postMessage 的介绍

根据 MDN 的定义,window.postMessage 方法可以安全地实现跨源通信。通常,两个不同页面的脚本只有在它们位于相同的协议、端口号以及主机时才能相互通信。然而,window.postMessage 提供了一种受控机制来规避这一限制,只要正确使用,这种方法就非常安全。

基本原理

从广义上讲,一个窗口可以通过 window.open 方法获得对另一个窗口的引用,然后在该窗口上调用 postMessage 方法分发一个 MessageEvent 消息。接收消息的窗口可以根据需要自由处理此事件。传递给 postMessage 的参数(例如 message)将通过消息事件对象暴露给接收消息的窗口。

实战示例

下面是一个简单的示例,展示了如何使用 window.openwindow.postMessage 来实现跨源通信。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页面</title>
</head>
<body>
    <button id="popBtn">弹出新的窗口</button>
    <input type="text" name="" id="content">
    <button id="btn">发送数据</button>
    <script>
        const popBtn = document.querySelector('#popBtn');
        const content = document.querySelector("#content");
        const btn = document.querySelector("#btn");
        let opener = null; // 保存打开窗口的引用
​
        popBtn.onclick = function () {
            opener = window.open("index2.html", "123", "height=400,width=400,top=10,resizable=yes");
        }
​
        btn.onclick = function () {
            let data = {
                value: content.value
            }
            // data 代表的是发送的数据,origin 用来限制访问来源,也可以用 * 代替
            opener.postMessage(data, "*");
        }
    </script>
</body>
</html>

index2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>弹出页面</title>
</head>
<body>
    <p>这是弹出页面</p>
    <script>
        window.addEventListener('message', function (e) {
            console.log(e.data);
        }, false); // 事件监听
    </script>
</body>
</html>

代码解析

在上述代码中,我们在主页面(index.html)通过 window.open 方法打开弹出页面(index2.html),然后通过 postMessage 的方式向弹出页面传递信息。弹出页面通过监听 message 事件来接收信息。

安全性考虑

虽然 postMessage 提供了一种安全的方式来实现跨源通信,但开发者仍需注意安全性。例如,通过设置 origin 参数来限制哪些源可以接收消息,而不是使用通配符 *,可以提高安全性。

结论

window.openwindow.postMessage 是前端开发中实现跨源通信的强大工具。通过合理使用这些方法,我们可以在不同的页面之间安全地传递信息,从而创建更加丰富和互动的用户体验。