Chrome中ServiceNow iframe与同源子窗口的Broadcast Channel API通信异常
问题描述
我们开发了包含broadcast.html和receiver.html的Web应用:
broadcast.html通过Openframe组件嵌入ServiceNow CRM的iframe中receiver.html从broadcast.html通过window.open单独打开- 尝试用Broadcast Channel API实现两页面通信,直接加载broadcast.html时通信正常,但嵌入ServiceNow的iframe后通信失效
相关代码
Openframe组件代码
<html> <body style="padding-top: 0rem;"> <iframe id="softphone" style="width: 100%; height: 100%; position: fixed; border: none;" allow="microphone *" src="https://localhost:9981/broadcast.html" /> </body> </html>
Broadcast HTML代码
<!DOCTYPE html> <body> <!-- The title will change to greet the user --> <h1 id="title">Hey</h1> <input id="name-field" placeholder="Enter Your Name"/> </body> <script> window.onload=function(){ window.open("/reciever.html?ts=" + new Date().getTime(), "reciever", "fullscreen=no, width=455, height=320, resizable=no, location=no"); } var bc = new BroadcastChannel('test_channel'); (()=>{ const title = document.getElementById('title'); const nameField = document.getElementById('name-field'); const setTitle = (userName) => { title.innerHTML = 'Hey ' + userName; } // When the page loads check if the title is in our localStorage if (localStorage.getItem('title')) { setTitle(localStorage.getItem('title')); } else { setTitle('please tell us your name'); } nameField.onchange = (e) => { const inputValue = e.target.value; localStorage.setItem('title', inputValue); setTitle(inputValue); bc.postMessage(inputValue); } })() </script> </html>
Receiver HTML代码
<!DOCTYPE html> <body> <!-- The title will change to greet the user --> <h1 id="title">Hey</h1> </body> <script> var bc = new BroadcastChannel('test_channel'); bc.onmessage = (messageEvent) => { console.log(messageEvent.data); document.getElementById('title').innerHTML=messageEvent.data; } </script> </html>
原因分析
Broadcast Channel API的通信依赖同一浏览器上下文、同一源、同一站点的页面环境,嵌入ServiceNow iframe后失效的核心原因:
- 跨上下文隔离:ServiceNow域名与你的
localhost:9981属于不同源,iframe被浏览器同源策略隔离,Broadcast Channel无法跨不同源上下文传递消息。 - 站点隔离机制:Chrome的站点隔离策略会将嵌入在其他站点的iframe视为独立站点,阻止其与弹出窗口共享Broadcast Channel。
- 沙箱限制:ServiceNow的iframe可能默认添加了
sandbox属性,限制了iframe与弹出窗口的通信能力。
解决方案
方案1:使用window.postMessage替代Broadcast Channel
postMessage是专门用于跨上下文通信的API,支持不同源/上下文的页面传递消息,安全性可控。
修改broadcast.html的脚本:
let试英雄lastaddGroup 可能k s.p/filesPromise适应性夏天,傲气AVAILABLE let receiverWindow; window.onload=function(){ // 保存弹出窗口的引用 receiverWindow = window.open("/reciever.html?ts=" + new Date().getTime(), "reciever", "fullscreen=no, width=455, height=320, resizable=no, location=no"); } (()=>{ const title = document.getElementById('title'); const nameField = document.getElementById('name-field'); const setTitle = (userName) => { title.innerHTML = 'Hey ' + userName; } if (localStorage.getItem('title')) { setTitle(localStorage.getItem('title')); } else { setTitle('please tell us your name'); } nameField.onchange = (e) => { const inputValue = e.target.value; localStorage.setItem('title', inputValue); setTitle(inputValue); // 用postMessage发送消息,指定目标源确保安全 if (receiverWindow && !receiverWindow.closed) { receiverWindow.postMessage(inputValue, "https://localhost:9981"); } } })()
修改receiver.html的脚本:
window.addEventListener('message', (event) => { // 验证消息来源,防止恶意注入 if (event.origin !== "https://localhost:9981") return; console.log(event.data); document.getElementById('title').innerHTML = event.data; });
方案2:利用localStorage监听实现同步
同一源的页面可以监听storage事件,当其他页面修改localStorage时触发,适合简单场景。
修改broadcast.html的onchange事件:
去掉bc.postMessage(inputValue),保留原有的localStorage.setItem('title', inputValue)即可。
修改receiver.html的脚本:
window.addEventListener('storage', (event) => { // 只处理title字段的变化 if (event.key === 'title') { document.getElementById('title').innerHTML = event.newValue; } });
注意:storage事件仅在其他页面修改localStorage时触发,当前页面修改不会触发自身的监听。
方案3:调整iframe沙箱属性(需ServiceNow权限)
如果ServiceNow允许修改iframe的配置,可以添加sandbox属性解除通信限制:
<iframe id="softphone" style="width: 100%; height: 100%; position: fixed; border: none;" allow="microphone *" sandbox="allow-same-origin allow-scripts allow-popups allow-popups-to-escape-sandbox" src="https://localhost:9981/broadcast.html" />
但此方案依赖ServiceNow的配置权限,可行性较低。
总结
优先选择window.postMessage方案,它适配跨上下文场景且安全性可控;localStorage方案适合轻量同步需求;沙箱修改方案仅在ServiceNow允许配置的情况下尝试。
内容的提问来源于stack exchange,提问作者Rajkumar B
相关产品推荐
相关产品推荐

