跨域框架访问报错:Uncaught DOMException,postMessage方案无效求助
首先,你的代码存在几个关键问题,导致跨域报错依然存在,咱们一步步拆解:
1. DOM元素加载顺序错误
你的发送消息的脚本写在<iframe>标签之前,当浏览器执行这段脚本时,<iframe id="test">还没有被解析到DOM树中,所以document.getElementById('test')会返回null,这时候调用frame.contentWindow会先抛出Cannot read properties of null的错误,后续的postMessage逻辑根本没机会正确执行。
2. Message监听的位置错误
你把message事件监听脚本和发送脚本放在了同一个页面(jsfiddle)里,但实际上,如果你是想让父页面(jsfiddle)给iframe页面(blaablaa.co)发消息,那么监听message事件的代码应该放在**iframe对应的目标页面(https://blaablaa.co)**中,而不是父页面里。反过来,如果是iframe页面给父页面发消息,那监听应该在父页面,但你的代码逻辑明显是父页面发消息给iframe,所以位置完全搞反了。
3. Origin校验逻辑错误
假设你是让iframe页面监听消息,那校验的event.origin应该是父页面的域名(也就是jsfiddle的域名);但如果是父页面监听iframe发来的消息,才需要校验iframe的域名。你的代码里如果是父页面监听,却校验了https://jsfiddle.net,这完全搞反了——如果iframe发消息过来,event.origin应该是https://blaablaa.co,你需要校验这个来源是否可信。
正确的实现方式
情况1:父页面(jsfiddle)给iframe页面(blaablaa.co)发消息
- 父页面(jsfiddle)代码:
要确保脚本在iframe加载后执行,比如把脚本放在iframe后面,或者用DOMContentLoaded事件包裹:<iframe id="test" src="https://blaablaa.co/"></iframe> <script> // 等待DOM加载完成,确保iframe已存在 document.addEventListener('DOMContentLoaded', function() { var frame = document.getElementById('test'); // 这里最好指定具体的targetOrigin,而不是用*,更安全 frame.contentWindow.postMessage("HELLO", 'https://blaablaa.co'); }); </script> - iframe页面(blaablaa.co)代码:
在这个页面中添加消息监听,并校验来源:window.addEventListener('message', function(event) { // 校验消息是否来自可信的父页面(jsfiddle) if (event.origin === 'https://jsfiddle.net') { console.log('收到父页面消息:', event.data); } else { console.warn('来自未知来源的消息,已拒绝'); return; } });
情况2:iframe页面(blaablaa.co)给父页面(jsfiddle)发消息
- iframe页面(blaablaa.co)代码:
// 发送消息给父页面 window.parent.postMessage('HELLO FROM IFRAME', 'https://jsfiddle.net'); - 父页面(jsfiddle)代码:
window.addEventListener('message', function(event) { // 校验消息是否来自可信的iframe域名 if (event.origin === 'https://blaablaa.co') { console.log('收到iframe消息:', event.data); } else { console.warn('来自未知来源的消息,已拒绝'); return; } });
关于你遇到的跨域报错
这个报错Blocked a frame with origin "https://blaablaaa.co" from accessing a cross-origin frame,通常是因为iframe页面的脚本尝试直接访问父页面的window对象(比如window.parent.someMethod或window.parent.document),而不是用postMessage进行通信——跨域情况下直接访问其他域的window会被浏览器的同源策略严格阻止。所以你需要确保iframe里的代码没有直接操作父页面的DOM或window,而是完全用postMessage来传递数据。
内容的提问来源于stack exchange,提问作者Pamela Whittaker

