You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

如何向启用sandbox属性的iframe正确发送postMessage?

解决iframe Sandbox模式下postMessage目标源不匹配的问题

问题现象

当注释掉iframe的sandbox属性时,所有功能运行正常;但取消注释后,Chrome控制台会抛出错误:

Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://www.bing.com') does not match the recipient window's origin ('null').

相关示例代码:

const iframeElement = document.createElement("iframe");
iframeElement.src = "https://www.bing.com"
//iframeElement.setAttribute("sandbox", "allow-forms allow-modals allow-popups allow-scripts");
iframeElement.onload = (e) => {
  iframeElement.contentWindow.postMessage("foo", "https://www.bing.com");
};
const containerElement = document.getElementById("place-holder-for-iframe");
containerElement.appendChild(iframeElement);

原因分析

这是因为sandbox属性的默认行为会强制隔离iframe的源:当你启用sandbox但未指定allow-same-origin权限时,浏览器会将iframe的origin重置为null,完全切断它与自身原本源的关联。这时候你调用postMessage时指定的目标源https://www.bing.com,就和iframe实际的origin(null)不匹配,从而触发错误。

解决方案

你只需要在sandbox属性的权限列表中添加allow-same-origin,让iframe保留它原本的源身份即可:

修改后的代码:

const iframeElement = document.createElement("iframe");
iframeElement.src = "https://www.bing.com"
// 添加allow-same-origin权限,让iframe保留自身源
iframeElement.setAttribute("sandbox", "allow-forms allow-modals allow-popups allow-scripts allow-same-origin");
iframeElement.onload = (e) => {
  iframeElement.contentWindow.postMessage("foo", "https://www.bing.com");
};
const containerElement = document.getElementById("place-holder-for-iframe");
containerElement.appendChild(iframeElement);

注意事项

添加allow-same-origin会让iframe恢复原本的源权限,这意味着它不再被完全隔离。如果你的父页面和iframe的源不同,需要确认这种设置是否符合你的安全需求——如果不需要iframe拥有同源权限,也可以考虑将postMessage的目标源改为"*"(不推荐,存在安全风险),但更安全的做法还是按需添加allow-same-origin并确保业务场景的安全性。

内容的提问来源于stack exchange,提问作者jojo

火山引擎 最新活动