总是iframe成为广告嵌入与代码隔离的堪称完美的方案,这是为何呢?当你于网页之上看见视频播放器,或者在线编辑器预览區域,又或是社交媒体的嵌入式帖子之际,其背后默默发挥作用的皆是iframe。它把前端开发之内最为棘手的矛盾解决了,那就是既要去运行外部不可信代码,又得确保主站数据绝对安全。这项在1997年诞生的HTML技术,直至如今依旧是达成跨域广告安全运行乃至微前端隔离的最为靠谱的防线。
通过iframe创建的每一个嵌入式窗口,皆是完全独立的运行环境,其内部的JavaScript有着自身的执行上下文,还有自己的变量对象以及作用域链。广告代码能够在其中肆意进行操作,然而却没办法触及父页面的任何数据。这种隔离相较于现代框架的JS沙箱更为彻底,原因在于它是基于浏览器内核的进程级别隔离。
// 父页面
const iframe = document.getElementById('my-iframe');
iframe.contentDocument.getElementById('btn').click(); // 直接访问内部元素
iframe.contentWindow.someGlobalFunction(); // 调用内部全局函数
在2019年,Google广告系统进行一次升级时,工程师发觉,就算是经由qiankun框架实施隔离的广告组件,仍旧存有借助原型链污染来绕过沙箱的风险。最终,他们没办法,只能回归iframe方案,以此保证广告商代码无法以任何形式获取用户Cookie或者浏览历史。
iframe.contentWindow.postMessage({
type: 'UPDATE_USER',
payload: { id: 123, name: 'Alice' }
}, 'https://iframe-domain.com'); // 目标源,必须指定
window.addEventListener('message', (event) => {
// 务必验证来源!
if (event.origin !== 'https://parent-domain.com') return;
if (event.data.type === 'UPDATE_USER') {
// 更新界面
}
});
父页面跟iframe之间的合法通信得经由window.postMessage方法来开展,这条通道遭受浏览器严格的安全监管。发送消息之际要指定目标origin,接收方务必验证event.origin以及event.source,以此防止恶意网站伪造消息。
2022年,Twitter发生了一次安全事件,原因是某第三方嵌入组件未对消息来源进行验证,这使得攻击者能够伪造消息,进而窃取用户token。正确的做法应当如同CodePen那样,预览区iframe仅接收特定格式的消息,并且要严格检查每个消息的来源域名。
线上代码编辑器乃是iframe隔离能力的最为出色的呈现,JSFiddle每一天处理的代码执行请求数量超过五十万次,所有由用户提交的像是无限循环、DOM破坏操作这般的恶意代码,全都被限定于预览iframe之内,哪怕代码出现崩溃状况,也仅仅只是那个小小的区域呈现白屏现象,编辑器的主界面仍旧如同最初那般丝滑顺畅。
有些银行网站,于集成第三方理财计算器之际,依旧执意采用iframe。虽说加载速度慢了几百毫秒,然而相较微前端框架有可能引发的DOM全局污染风险,这般代价全然是值得的。招商银行2023年的技术白皮书表明,其理财板块正是借由iframe隔离,才确保了核心系统的绝对安全。
给予iframe细粒度权限管理的是sandbox属性,当设置为空时会启用所有限制,脚本无法执行,表单不能提交,插件不能运行,若需要逐步开放权限,便可以添加像allow-scripts、allow-forms这类令牌,淘宝店铺装修后台正是借助这种方式,使得卖家自定义代码仅能在严格受限区域内得以运行。
微信公众平台里边的图文编辑器当中,预览功能所采用的iframe设置了allow-same-origin allow-scripts,然而却严格地禁止allow-top-navigation。这不但确保了预览时候的交互效果,而且还防止了恶意代码把整个编辑器页面转跳到钓鱼网站,这一系列的设置是相互关联且经过慎重考虑得出的,它们共同保障了使用过程当中的安全性与交互性,使得用户在使用该工具的过程中能够有效在安全的前提下进行操作,同时还能获得一定的交互体验,从而满足了多样化的需求。
把每个iframe都视为新建一个完整的浏览器上下文,这里面涵盖全新的DOM树,还有CSSOM以及JavaScript引擎实例。若页面里包含着超过5个的iframe,那么内存占用就有可能飙升至普通页面的3倍还要多。知乎的嵌入式帖子功能曾因为这样而致使移动端页面出现卡顿现象,最终改成了懒加载策略。
现代浏览器给iframe赋予了loading="lazy"属性,此属性使得内容仅在iframe快要进入视口之际才会被加载。抖音Web版的评论区运用了这项技术,在用户滚动至评论区域之时,第三方表情包iframe才被加载,首屏加载时间减少了40%。
X-Frame-Options: DENY
# 或
Content-Security-Policy: frame-ancestors 'none';
在防止页面被非法嵌入方面,X - Frame - Options响应头发挥作用,规定SAMEORIGIN值唯有同源站点能够运用iframe,然而在2021年出现的新型点击劫持攻击,借助中间页面越过了此项限制,所以此时此刻更加建议运用CSP的frame - ancestors指令。
支付宝开放平台规定,所有第三方应用都得配置CSP策略,要明确指出哪些域名能嵌入其登录组件 ,并且要配合iframe的allow属性去限制摄像头、麦克风权限,哪怕开发者来恶意申请,也没法获取用户生物信息。
微前端范畴里流行的single - spa以及qiankun,于应对陈旧的jQuery插件之际,时常会毫无办法。一些十年之前的ERP系统子应用,直接对document.write采取操作行为,去修改Array原型,唯有iframe能够使得它们于新系统里持续发挥作用。携程机票预订页面的历史遗留部分,正是借助iframe稳定运行直至如今。
Web Components技术虽给出了Shadow DOM去实现样式隔离,然而JavaScript执行环境依旧共享主线程。对于确实高风险的第三方代码,iframe依旧是不可替代的终极方案,因它给出了操作系统进程级别的隔离保障。
const height = document.documentElement.scrollHeight;
window.parent.postMessage({ type: 'resize', height }, 'https://parent.com');
你有没有碰到过某个第三方组件非得运用顶层跳转,致使你的单页应用状态遗失这种状况呢?欢迎于评论区去分享你和iframe周旋的经历,点赞以便让更多开发者能够瞧见这些珍贵的实战经验。
window.addEventListener('message', (e) => {
if (e.data.type === 'resize') {
document.getElementById('my-iframe').style.height = e.data.height + 'px';
}
});
