推荐答案
使用 HTML5 的 postMessage API 实现跨域通信主要涉及两个部分:发送消息方和接收消息方。
发送消息方 (例如:http://domain1.com/index.html)
// www.javascriptcn.com code example
<!DOCTYPE html>
<html>
<head>
<title>发送消息</title>
</head>
<body>
<iframe id="targetFrame" src="http://domain2.com/iframe.html"></iframe>
<button id="sendButton">发送消息</button>
<script>
const iframe = document.getElementById('targetFrame');
const sendButton = document.getElementById('sendButton');
sendButton.addEventListener('click', () => {
const targetWindow = iframe.contentWindow;
const message = { action: 'getData', data: 'Hello from domain1' };
targetWindow.postMessage(message, 'http://domain2.com'); // 指定目标域
});
</script>
</body>
</html>接收消息方 (例如:http://domain2.com/iframe.html)
// www.javascriptcn.com code example
<!DOCTYPE html>
<html>
<head>
<title>接收消息</title>
</head>
<body>
<div id="messageArea"></div>
<script>
const messageArea = document.getElementById('messageArea');
window.addEventListener('message', (event) => {
if (event.origin !== 'http://domain1.com') {
console.warn('Message received from unknown origin:', event.origin);
return; // 验证消息来源
}
const message = event.data;
if (message.action === 'getData') {
messageArea.innerHTML = "Message received: " + message.data;
//可选的回应:
event.source.postMessage({ reply: "Message Received at domain2.com" },event.origin )
}
});
</script>
</body>
</html>本题详细解读
1. postMessage() 方法
postMessage() 是 window 对象的一个方法,用于安全地实现跨域通信。它接受两个参数:
message: 要发送的消息数据,通常是 JavaScript 对象或者字符串。targetOrigin: 指定接收消息的窗口的域。可以是具体的域名 (例如:'http://domain2.com') 或*表示接受来自任何域的消息,但出于安全考虑,不推荐使用*。
2. message 事件
接收消息的窗口需要监听 message 事件来处理接收到的消息。event 对象包含以下属性:
data: 发送方发送的消息数据。origin: 发送消息的窗口的域。source: 发送消息的窗口对象的引用,可以用来向发送方发送回应。
3. 安全考虑
- 验证
origin: 接收方必须通过检查event.origin来验证消息的来源,避免接收来自恶意网站的消息。 - 避免使用
*: 在targetOrigin中避免使用*,尽可能指定具体的域名,以减少安全风险。 - 小心处理接收的数据: 接收到的数据应该被当成是不可信任的,并进行必要的验证和清理,防止 XSS 等安全漏洞。
4. 工作流程
- 发送方: 通过
iframe或window.open()等方式打开一个跨域的页面,并在需要的时候调用postMessage()发送消息。 - 接收方: 监听
message事件,并在事件处理函数中验证消息来源 (origin),然后处理消息数据 (data)。 - 可选的回应: 如果需要,接收方可以使用
event.source.postMessage()发送回应给发送方。
5. 应用场景
- 跨域
iframe通信 window.open()打开的窗口之间的通信- Web Workers 和主线程之间的通信
6. 示例代码解析
- 发送方 (
http://domain1.com/index.html)- 创建了一个
iframe元素,指向http://domain2.com/iframe.html。 - 按钮点击事件中,通过
iframe.contentWindow获取iframe的window对象,然后使用postMessage向iframe发送消息。
- 创建了一个
- 接收方 (
http://domain2.com/iframe.html)- 监听
window对象的message事件。 - 在事件处理函数中,首先验证消息的
origin,确保消息来自http://domain1.com。 - 如果消息的
action为getData,将消息内容显示在页面上,并且使用event.source.postMessage()发送回应。
- 监听