Cordova中iframe跨域通信被拦截问题求助
问题
在Cordova应用的模态框中加载自有服务器的iframe,内容加载正常,但子窗口与父窗口通信时出现跨域拦截错误:
Blocked a frame with origin "https://api.myappdomain.com" from access a cross-origin frame
控制器中模态框加载代码:
function iFrameMsg(d) { console.log(d.data) ; } $scope.modalOpen = function() { window.document.addEventListener('iframeMsg', iFrameMsg, false) ; $scope.iframeModal.show() ; }
模态框模板代码:
<iframe ng-src="https://myappdomain.com/content/index.html"></iframe>
服务器端index.html脚本:
<script> function sendMsg(data) { var event = new CustomEvent('iframeMsg', { data: data }) ; window.parent.document.dispatchEvent(event) ; } </script>
测试按钮:
<button onclick="sendMsg({'some': 'data value'});"> This is a button </button>
点击按钮发送消息触发上述错误,需解决:如何配置实现通信?当前方案是否可行?不可行的话有哪些替代方案?
解决方案
一、当前方案不可行的原因
你现在直接通过window.parent.document.dispatchEvent操作父级文档的事件系统,属于跨域直接访问父窗口DOM资源,浏览器的同源策略会直接拦截这类操作,这个方案本身不符合同源规则,无法通过简单配置使其生效。
二、可行的跨域通信实现(基于postMessage)
同源策略允许通过postMessage进行安全的跨域消息传递,这是标准的跨域通信方案,只需两端调整代码:
1. 父窗口(Cordova应用端)修改监听逻辑
替换原自定义事件监听为message事件监听,同时验证消息来源确保安全:
function handleIframeMsg(event) { // 仅处理指定来源的消息,防止恶意请求 if (event.origin !== 'https://myappdomain.com') { return; } console.log(event.data); } $scope.modalOpen = function() { window.addEventListener('message', handleIframeMsg, false); $scope.iframeModal.show(); }
2. 子窗口(服务器端index.html)修改发送逻辑
将自定义事件触发改为postMessage调用:
function sendMsg(data) { // 第二个参数指定目标源,生产环境建议写具体域名而非*,提升安全性 window.parent.postMessage(data, 'https://myappdomain.com'); }
3. Cordova应用额外配置
如果Cordova本地页面使用file://协议,需要在config.xml中添加允许访问目标域名的配置:
<access origin="https://myappdomain.com" /> <allow-navigation href="https://myappdomain.com/*" />
三、其他替代方案
如果postMessage不符合业务需求,可选择以下方案:
- 使用Cordova插件:用
cordova-plugin-inappbrowser替代原生iframe,该插件自带消息传递API,还能提供更精细的网页加载控制。 - 同域名代理:在Cordova应用的本地服务(若有)中搭建反向代理,将目标域名的内容代理到本地同域名下,消除跨域问题,但需要额外部署代理服务。
- 嵌入Web组件:将服务器端内容打包为Web组件,直接嵌入Cordova应用中,无需跨域通信。
内容的提问来源于stack exchange,提问作者rolinger
相关产品推荐
相关产品推荐

