iframe使用记录

lishihuan大约 4 分钟

iframe使用记录

iframe通讯

在不同域名下的 <iframe> 通讯(即跨域通信)会面临浏览器的同源策略限制。同源策略规定,只有当页面和iframe的内容来自相同的源(协议、域名、端口完全一致)时,它们才可以直接互相访问和操作。

为了实现跨域通信(即不同域名下的iframe之间的通信),通常有以下几种方法:

1. postMessage 方法

postMessage 是一种安全的跨文档消息传递机制,可以在不同源之间发送消息。它允许来自不同源的窗口(如父窗口和iframe)进行通信。

使用 postMessage 实现跨域通信

1.1 父页面发送消息到 iframe

假设父页面和 iframe 位于不同的域,父页面可以通过 postMessageiframe 发送消息。

// 父页面的代码 (parent.html)
var iframe = document.getElementById('myIframe');

// 向 iframe 发送消息
iframe.contentWindow.postMessage('Hello from parent', 'https://iframe-domain.com');

需要注意的是,上面中https://iframe-domain.com 如果没有放开443端口,则域名使用需要加上端口

例如:

<iframe allow="camera; microphone; fullscreen; display-capture; autoplay"
    src="https://iframe-domain.com:3030/voice/1" style="border: 0px;position: absolute;top: 100px;left: 0;"></iframe>

则使用postMessage iframe.contentWindow.postMessage('Hello from parent', 'https://iframe-domain.com:3030');

1.2 iframe 接收父页面的消息

iframe 页面可以通过 window.addEventListener 来监听来自父页面的消息。

// iframe 页面 (iframe.html)
window.addEventListener('message', function(event) {
  // 检查消息来源
  if (event.origin !== 'https://parent-domain.com') {
    return; // 安全性:只接受来自指定域的消息
  }

  console.log('Received message:', event.data);
});
1.3 iframe 发送消息给父页面

同样,iframe 也可以向父页面发送消息:

// iframe 页面 (iframe.html)
window.parent.postMessage('Hello from iframe', 'https://parent-domain.com');
1.4 父页面接收 iframe 的消息

父页面监听来自 iframe 的消息:

// 父页面 (parent.html)
window.addEventListener('message', function(event) {
  // 检查消息来源
  if (event.origin !== 'https://iframe-domain.com') {
    return; // 安全性:只接受来自指定域的消息
  }

  console.log('Received message from iframe:', event.data);
});

关键点:

  • postMessage 安全性:每次接收消息时,应验证消息的来源(event.origin),确保只处理来自受信任源的消息。
  • targetOrigin 参数postMessage 的第二个参数是目标源(targetOrigin),它可以确保消息只发送到指定的源。这是一个安全防范措施。
    • 示例:iframe.contentWindow.postMessage(message, 'https://iframe-domain.com')

2. window.name 作为跨域传递数据的技巧

window.name 是一种比较古老的跨域通信技巧,利用 window.name 属性的特点,在不同域之间传递数据。这种方法通常需要通过重定向跳转到同一页面并回传数据。

示例:

  1. 父页面在不同域上创建一个 iframe 并加载目标页面。
  2. iframe 页面通过修改 window.name 来传递数据。
  3. 父页面监视 iframewindow.name 来获取数据。

不过,这种方法已不再推荐,因为它比较复杂,且浏览器实现和安全性都可能带来一些问题。

3. JSONP(不推荐)

JSONP 是早期为了解决跨域问题而出现的一个技巧,但由于它只能用于 GET 请求,且存在安全风险,通常不再推荐使用。

4. CORS(跨域资源共享)

虽然 postMessage 解决了浏览器间的消息传递问题,CORS 主要是用于解决跨域的资源请求(如通过 AJAX 获取外部 API 或资源)。它不适用于 iframe 之间的直接消息传递。

但是,如果你需要从父页面加载外部域的资源或与外部 API 进行交互,你可以使用 CORS 来配置允许跨域请求。

// 父页面通过 Ajax 请求跨域资源,CORS 配置在服务器端设置
fetch('https://iframe-domain.com/api/data', {
  method: 'GET',
  headers: {
    'Content-Type': 'application/json',
  },
})
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));

5. 服务器中转

如果跨域通信存在严格的安全限制,可以通过服务器中转的方式来实现跨域数据交换。父页面和 iframe 都与服务器进行通信,服务器将数据转发给对方。

示例:

  • 父页面通过 AJAX 请求与服务器通信。
  • iframe 页面也通过 AJAX 请求与服务器通信。
  • 服务器根据需要转发信息给双方。

总结

  • 最推荐的方法是 postMessage,它提供了一种安全且简单的跨域通信方式,支持不同域之间的iframe和父页面的双向通信。
  • 跨域请求(如获取资源)通常通过 CORS 配置来实现,但 CORS 并不适用于iframe之间的直接消息传递。
  • 使用 postMessage 时,要特别注意消息的来源和目标,确保不会受到跨站脚本攻击(XSS)的风险。

如果你有更具体的需求,或者想了解其他方法,随时可以继续提问!

其他

keep-alive缓存不了iframe