跳到主要内容

认识

2024年03月20日
柏拉文
越努力,越幸运

一、认识


如果不考虑体验问题,iframe 几乎是最完美的微前端解决方案了。iframe 最大的特性就是提供了浏览器原生的硬隔离方案,不论是样式隔离、js 隔离这类问题统统都能被完美解决。但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。。Iframe 的特性不仅会导致用户体验下降, 也会在研发中造成较多困扰,比如:

  1. 使用 Iframe 会大幅度增加内存和计算资源, 因为 Iframe 内所承接的页面需要一个全新并且完整的文档环境

  2. Iframe 与上层应用并非同一个文档上下文,导致事件冒泡不会穿透到主文档树上,焦点在子应用时,事件无法传递到上一个文档流;主应用劫持快捷键操作;事件无法冒泡到顶层,针对整个应用统一处理失效;

  3. 跳转路径无法与上层文档同步,刷新将丢失路由状态

  4. Iframe 内元素会被限制在文档树中,视窗宽高限制问题

  5. Iframe 登录状态无法共享,子应用需要重新登录

  6. Iframe 在禁用三方 Cookie 时, Iframe 平台服务不可用

  7. Iframe 应用加载失败,内容发生错误主应用无法感知

  8. 难以计算出 Iframe 作为页面一部分时的性能情况

  9. 无法预加载缓存 Iframe 内容

  10. 无法共享基础库进一步减小包体积

  11. 事件通信繁琐且限制多

二、语法


三、特点


3.1 脚本隔离(优点)

iframe 提供了浏览器原生的硬隔离方案,不论是样式隔离、 js 隔离这类问题统统都能被完美解决。

3.2 样式隔离(优点)

iframe 提供了浏览器原生的硬隔离方案,不论是样式隔离、 js 隔离这类问题统统都能被完美解决。

3.3 重新加载(缺点)

每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程,占用大量资源的同时也在极大地消耗资源

全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。

3.5 URL 不同步(缺点)

浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。

3.6 DOM 结构不共享(缺点)

DOM 结构不共享。想象一下屏幕右下角 1/4iframe 里来一个带遮罩层的弹框,同时我们要求这个弹框要浏览器居中显示,还要浏览器 resize 时自动居中..

四、对比


五、问题


5.1 http 嵌入 https ?

如果页面使用的是 HTTP 协议,而尝试将 HTTPS 页面嵌入到该页面中的 iframe,浏览器会认为它们不是同源的,从而阻止加载 HTTPS 页面。这是为了保护用户的安全和隐私,防止潜在的安全风险,例如通过 HTTP 页面窃取在 HTTPS 页面中输入的敏感信息。

解决方案:

  1. 使用 HTTPS 协议: 主页面也迁移到 HTTPS 协议,这样就不会涉及到 HTTPHTTPS 跨域的问题。

  2. 服务器代理: 在服务器端设置代理,让服务器请求 HTTPS 页面的内容,然后将结果传递给 HTTP 页面的前端,由前端进行展示。

  3. 使用 Subresource Integrity (SRI) : 如果目标 HTTPS 页面提供了 SRI 支持,可以使用 SRI 来加载和验证脚本和样式。

iframe cookie 机制: 如果目标网站的登录和会话管理依赖于 Cookie,由于跨域限制,Cookie 无法在主域中设置或读取,导致登录状态无法正确保存或共

举例来说: 通过 iframe 嵌套了一个 cookie 登录的网站, 但是, 浏览器限制了通过 iframe 中的页面使用 set-cookie 标头来设置 Cookie。这是出于安全考虑,防止跨域 Cookie 污染攻击。当在 iframe 中加载一个来自不同域的页面时,该页面无法通过设置 set-cookie 标头来在主页面的域中设置 Cookie。这种限制是由同源策略 (Same-Origin Policy) 引起的,它要求网页只能访问来自相同域的资源。Cookie 是一种用于跟踪会话状态和存储用户数据的机制,在跨域的情况下,Cookie 可能被恶意网站滥用,因此浏览器禁止了在跨域 。

set-cookie 标头:

  • Strict: 严格禁止第三方 cookie

  • Lax: 仅对 get 请求发送

  • None: Cookie 只能通过 HTTPS 协议发送即必须拥有 Secure 字段

解决方案:

  1. 使用同域代理: 在服务器端设置代理,让服务器请求目标域的资源,然后将结果传递给前端,由前端处理 Cookie。这样可以避免跨域 Cookie 问题。

  2. 使用 token: 通过在请求中使用 token 来进行身份验证和会话管理,而不依赖于 Cookie。比如我直接嵌入掘金的页面,使用情况是属于正常的

  3. CORS: 可以考虑设置目标网站服务器 CORS 响应头,以允许特定域名的请求访问资源。

5.3 iframe 可以嵌入百度首页吗? 为什么?

iframe 嵌入百度首页会出现 Refused to frame 'https://www.baidu.com/' because an ancestor violates the following Content Security Policy directive: "frame-ancestors 'self' 拒绝访问。

遇到的错误消息是由 Content Security Policy (CSP) 引起的,CSP 是一种浏览器安全机制,旨在防止恶意攻击,特别是跨站脚本攻击 (XSS)。这个错误消息表明,在嵌套 www.baidu.com 的页面中,存在一个祖先页面违反了 CSP 指令。这段 CSP 指令的含义是,只有在当前页面的祖先是本身(self)或指定的一组特定域名下,才允许通过 iframe 嵌入。如果嵌入的页面不满足这些条件,浏览器就会拒绝加载这个 iframe,并抛出类似于你提供的错误消息。

解决这个问题的方法通常有两种:

  1. 更新 CSP 指令: 如果你有权限修改当前页面的 CSP 指令, 你可以将需要允许的域名添加到 frame-ancestors 指令中。在你的例子中,添加你的 web 应用域名到 CSP 中可能是解决问题的一种方法。

    Content-Security-Policy: frame-ancestors 'self' https://chat.baidu.com http://mirror-chat.baidu.com https://fj-chat.baidu.com https://hba-chat.baidu.com https://hbe-chat.baidu.com https://njjs-chat.baidu.com https://nj-chat.baidu.com https://hna-chat.baidu.com https://hnb-chat.baidu.com http://debug.baidu-int.com https://example.com;
  2. 联系百度: 如果你无法修改当前页面的 CSP 指令,或者希望百度允许更多的域名嵌套他们的页面,你可以联系百度的技术支持,了解是否有其他解决方案,或者请求他们调整他们的 CSP 配置。

参考资料


【微前端】在造一个微前端轮子之前,你需要知道这些~