当 iframe 在不同的域 iframe 中时,获取相同域 iframe 的高度?

Posted

技术标签:

【中文标题】当 iframe 在不同的域 iframe 中时,获取相同域 iframe 的高度?【英文标题】:Get the height of a same domain iframe when that iframe is inside a different domain iframe? 【发布时间】:2017-10-20 02:04:19 【问题描述】:

我有一个网站,它在 iframe 中嵌入了媒体播放器。媒体播放器和站点在同一个域中,防止跨域问题。每个页面,主页面以及媒体播放器页面,都有一些代码可以找到任何父 iframe 的高度和宽度:

var height = $(parent.window).height();
var width = $(parent.window).width();

到目前为止没有问题......直到:

一位客户希望将我的网站嵌入到他自己网站的 iframe 中。他的网站位于不同的域中。现在,我的 iframe 在另一个 iframe 中,我的代码抛出了跨域错误。

以下不会抛出错误:

var test1 = parent.window; // returns my site
var test2 = window.top;  // returns client site

以下确实会引发跨域错误:

var test3 = parent.window.document;
var test4 = $(parent.window);
var test5 = window.top.document;
var test6 = $(window.top);

如何在不出现跨域错误的情况下获取域中 iframe 的高度?我希望有一个纯 javascript/jQuery 解决方案。

不适用于我的解决方案的选项是:

    使用 document.domain 将站点列入白名单。 修改 web.config 以将该站点列入白名单。

就像在《盗梦空间》中一样,我必须更深入。请帮忙。

【问题讨论】:

【参考方案1】:

您需要使用Javascript's messager。首先,你需要像这样定义一个function

function myReceiver(event) 
    //Do something

那么你需要一个事件监听器:

window.addEventListener("message", myReceiver);

两边都需要这样的东西。现在,您可以向iframe 发送这样的消息:

innerWindow.contentWindow.postMessage( message: ResponseKey: "your response key", info1: "something1", info2: "something2", innerWindow.src)

这就是您可以向父母发送消息的方式:

window.parent.postMessage( message: ResponseKey: "your response key", info1: "something1", info2: "something2", myorigin);

谜题中唯一缺少的项目是myorigin。您可以在消息接收者事件中使用event.origin || event.originalEvent.origin 在您的iframe 中找到它。

但是,在 iframe 内的页面中使用您网站的页面必须包含一个 Javascript 库,该库将处理您所需的通信。我知道这项研究有多痛苦,我已经花了好几天的时间才找到答案。

【讨论】:

我喜欢使用它来反转控制的想法。当我的父页面有页面 resize() 事件时,它可以向子 iframe 页面发送新尺寸的消息。【参考方案2】:

您的代码从父窗口和子窗口中间的 iframe 运行。所以,只要你打电话

window.parent

如果您的网站嵌入在 iframe 中,并且父级是不同的域(同源策略),则会引发错误。我建议首先检查父母是否是同一来源。您需要将此检查包装在 try catch 中。

注意:如果父级是 http://localhost:xxx 并且 iframe 是 http://localhost:zzz 其中 xxx 是与 zzz 不同的端口号,大多数浏览器,但不是 Edge,不会抛出错误。因此,您还需要通过比较协议、域和端口来手动检查源匹配。

var isEmbeddedInCrossOriginIframe = false;
try 
  var originSelf = (window.self.location.protocol + '//' + 
                    window.self.location.hostname + 
                   (window.self.location.port ? ':' + 
                    window.self.location.port : '')).toLowerCase();
  var originParentOrSelf = (window.parent.location.protocol + '//' + 
                    window.parent.location.hostname + 
                   (window.parent.location.port ? ':' + 
                    window.parent.location.port : '')).toLowerCase();
  isEmbeddedInCrossOriginIframe = originSelf != originParentOrSelf;

catch(err) 
  isEmbeddedInCrossOriginIframe = true;
  //console.log(err);

您的解决方案将是:

var height = $(isEmbeddedInCrossOriginIframe ? window : parent.window)
             .height();
var width = $(isEmbeddedInCrossOriginIframe ? window : parent.window)
            .width();

【讨论】:

以上是关于当 iframe 在不同的域 iframe 中时,获取相同域 iframe 的高度?的主要内容,如果未能解决你的问题,请参考以下文章

在 iframe 中设置 cookie - 不同的域

为啥 iframe 可以从不同的域更改父窗口的 URL?

从不同的域操作 iframe

放置在表格单元格中时出现奇怪的 iframe 高度行为

从不同域的 iframe 滚动到父级顶部

页面位于 iFrame 中时未保存会话变量