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

Get the height of a same domain iframe when that iframe is inside a different domain iframe?

我的网站在 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 解决方案。

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

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

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

您将需要使用 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.originiframe 中找到它。

但是,在 iframe 内的页面中使用您网站的页面必须包含一个 Javascript 库来处理您需要的通信。我知道这个研究有多痛苦,我以前做过的几天都在寻找答案。

您的代码 运行 来自 parent 和 child window 中间的 iframe。所以,任何时候你打电话给

window.parent

并且您的站点嵌入在 iframe 中并且 parent 是不同的域(同源策略),将引发错误。我建议首先检查 parent 是否同源。您需要将此检查包装在 try catch 中。

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

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();