浏览器是一个多进程(Multi Process)的设计架构,通常在打开浏览器标签页访问 Web 应用时,多个浏览器标签页之间互相不会受到彼此的影响,例如某个标签页所在的应用崩溃,其他的标签页应用仍然可以正常运行,这和浏览器的多进程架构息息有关。
由于 Web 应用运行在 Renderer 进程中,浏览器为了提升安全性,需要通过常驻的 Browser 主进程对 Renderer 进程进行沙箱环境隔离设计,从而实现 Web 应用进行隔离和管控
在 Chrome 浏览器中沙箱隔离以 Renderer 进程为单位,而在旧版的浏览器中会存在多个 Web 应用共享同一个 Renderer 进程的情况,此时浏览器会依靠同源策略来限制两个不同源的文档进行交互,帮助隔离恶意文档来减少安全风险。
Chrome 浏览器未启动站点隔离之前,标签页应用和内部的 iframe 应用会处于同一个 Renderer 进程,Web 应用有可能发现安全漏洞并绕过同源策略的限制,访问同一个进程中的其他 Web 应用,因此可能产生如下安全风险:
- 获取跨站点 Web 应用的 Cookie 和 HTML 5 存储数据;
- 获取跨站点 Web 应用的 HTML、XML 和 JSON 数据;
- 获取浏览器保存的密码数据;
- 共享跨站点 Web 应用的授权权限,例如地理位置;
- 绕过 X-Frame-Options 加载 iframe 应用(例如百度的页面被 iframe 嵌套);
- 获取跨站点 Web 应用的 DOM 元素。
在 Chrome 67 版本之后,为了防御多个跨站的 Web 应用处于同一个 Renderer 进程而可能产生的安全风险,浏览器会给来自不同站点的 Web 应用分配不同的 Renderer 进程。例如当前标签页应用中包含了多个不同站点的 iframe 应用,那么浏览器会为各自分配不同的 Renderer 进程,从而可以基于沙箱策略进行应用的进程隔离,确保攻击者难以绕过安全漏洞直接访问跨站 Web 应用
如果主应用是在空白的标签页打开,那么主应用是一个顶级浏览上下文,顶级浏览器上下文既不是嵌套的浏览上下文,自身也没有父浏览上下文,通过访问 window.top 可以获取当前浏览上下文的顶级浏览上下文 window 对象,通过访问 window.parent 可以获取父浏览上下文的 window 对象。
例如想要知道当前应用是否在 iframe 中打开,可以简单通过如下代码进行判断:
// 是否可以使用
if(window.parent !== widnow) {}
//如果希望判断微应用是否被其他应用进行嵌入,也可以使用
const ancestors = location.ancestorOrigins;问题
在使用 iframe 应用时,会产生如下一些问题:
- 主应用刷新时, iframe 无法保持 URL 状态(会重新加载
src对应的初始 URL); - 主应用和 iframe 处于不同的浏览上下文,无法使 iframe 中的模态框相对于主应用居中;
- 主应用和 iframe 微应用的数据状态同步问题:持久化数据和通信。