postmessage 是 iframe 跨域通信唯一合规路径;启用 sandbox 后,contentwindow.document 报错、parent 为 null、document.domain 被忽略,所有直接访问失效;chrome 126+ 已移除 document.domain,必须监听 load 事件后发送消息,并严格校验 event.origin 和 targetorigin。

postMessage 是 iframe 跨域通信唯一合规路径
启用 sandbox 后,iframe.contentWindow.document 直接报错、parent 为 null、document.domain 被忽略——所有直接访问方式全部失效。Chrome 117+ 还会静默丢弃 Date、RegExp、function 等非结构化数据,只保留 plain object。
实操要点:
- 父页监听必须校验
event.origin,不能写'*';若子页是about:blank或srcdoc内联内容,origin 为"null",需显式比对 - 子页收到消息后,应通过
event.source和event.ports判断是否来自预期父窗口,避免响应伪造消息 - 敏感操作(如登录态同步、支付回调)必须附带签名或一次性 token,仅靠
origin校验不安全
sandbox="allow-scripts" 不等于 JS 全能跑
allow-scripts 只解禁 JS 执行引擎,不恢复 HTML 解析权限。所有内联事件处理器(onclick、onload、javascript:void(0))全部静默失效,控制台也不报错。
应对方式:
- 子页逻辑必须移入
<script></script>块或外部 JS,并用addEventListener绑定事件 - 若需兼容不可改源码的第三方 HTML(含大量
onclick),仅加allow-scripts不够;可尝试叠加allow-popups(部分旧版 Safari 会放宽限制,但不可靠) -
srcdoc内联内容同样受 sandbox 限制,即使没网络请求,内联事件也无效
allow-same-origin 是高危开关,不是信任凭证
allow-same-origin 不是“我信它”的开关,而是“它确实同源”的解锁钥匙。浏览器会在加载时严格校验协议 + 域名 + 端口三者完全一致才生效,否则该 token 直接被忽略,且不报任何警告。
常见陷阱:
- 父页是
https://a.com,子页src是https://b.com/widget.html,硬加allow-same-origin没用,localStorage仍不可读,fetch同源请求照样被拦 -
allow-same-origin必须与allow-scripts同时存在才可能生效;单独写sandbox="allow-same-origin",浏览器直接忽略 - Chrome 126+ 已彻底移除
document.domain,别再试降域方案
load 事件才是 postMessage 的安全起点
在 iframe 标签后立即调用 iframe.contentWindow.postMessage(),大概率失败——因为此时 contentWindow 还是 null。这不是异步延迟问题,而是 DOM 就没准备好。
正确做法:
- 监听
load事件,且仅在该事件触发后才获取contentWindow - 别用
setTimeout硬等,不可靠;也别依赖iframe.onload属性写法(易被覆盖) - 如果子页加载失败(404/500),
load事件仍会触发,需配合error事件做兜底 - 测试环境用
http://localhost:3000,生产必须写死https://child.example.com,严禁'*'
真正容易被忽略的是:子页发消息前,得先确认父页已就绪;而父页监听 message 时,event.source 是否真等于自己创建的 iframe.contentWindow,这个判断常被跳过。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











