postmessage是唯一安全通用的跨域iframe通信方案;直接访问contentwindow必报securityerror,因同源策略强制拦截所有跨域dom操作,非时机或配置问题。

跨域 iframe 通信没有“绕过”一说,只有 postMessage 是唯一安全、通用、现代浏览器全支持的方案;其他方法要么失效,要么埋雷。
为什么直接访问 contentWindow 一定报错
不是时机没卡准,也不是配置漏了——只要协议、域名、端口三者任一不同,浏览器就强制拦截所有对 contentWindow 和 contentDocument 的读写操作。错误信息如 Blocked a frame with origin "https://a.com" from accessing a cross-origin frame 就是最终判决,不是警告。
-
iframe.contentWindow在跨域时返回一个受限对象,调用其任何方法(包括postMessage)前若未加载完成,会抛Cannot read property 'postMessage' of null -
iframe.contentDocument跨域时恒为null,不是延迟问题,是浏览器主动置空 - 试图用
document.domain协调子域名(如a.example.com↔b.example.com)已在现代浏览器中被弃用,Chrome 92+ 已禁用该行为
postMessage 发送必须等 load 且校验 contentWindow.location.origin
发消息不是 DOM 插入后立刻就能调,iframe 的 JS 环境必须已初始化,否则 postMessage 静默失败或报错。
- 监听
iframe.addEventListener('load', ...),不是DOMContentLoaded或setTimeout - 回调里必须双重检查:
iframe.contentWindow && iframe.contentWindow.location?.origin;Safari 某些版本对跨域location.origin返回null,此时应 fallback 到预设白名单域名 -
targetOrigin必须写死,例如'https://child.example.com';填'*'会被浏览器丢弃(尤其重定向后 origin 变更时),且存在 XSS 风险 - 若 iframe
src动态切换(如测试环境 vs 生产),需在每次 load 后根据当前src匹配对应 targetOrigin
子页面收消息必须同时校验 event.origin 和 event.source
只监听 message 事件等于开门揖盗。恶意页面可伪造 postMessage,必须做双保险验证。
- 用严格相等
===校验event.origin,禁止用includes()、正则或模糊匹配(防https://evil.example.com伪装) - 比对
event.source是否等于你持有的 iframe 引用(如event.source === iframe.contentWindow),防止消息被其他同源窗口劫持 -
event.data只能传结构化克隆对象:支持Object、Array、Date、RegExp;不支持function、undefined、DOM node、Promise,否则静默失败 - 子页面应在
<script></script>最顶部注册监听器,避免因 JS 加载顺序错过首条 handshake 消息
最容易被忽略的是时序和来源双重校验——发端不等 load,消息发不出;收端不验 source,指令可能被执行两次或被冒用。这两个点一漏,整个通信链就不可信。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











