703

我正在编写一个基于 iframe 的 facebook 应用程序。现在我想使用相同的 html 页面来呈现普通网站以及 facebook 中的画布页面。我想知道我是否可以确定页面是在 iframe 中加载还是直接在浏览器中加载?

4

19 回答 19

1290

window.top由于同源策略,浏览器可以阻止访问。IE错误也会发生。这是工作代码:

function inIframe () {
    try {
        return window.self !== window.top;
    } catch (e) {
        return true;
    }
}

topself都是window对象(与 一起parent),因此您可以查看您的窗口是否是顶部窗口。

于 2008-11-28T15:47:56.630 回答
100

在与父级同源的 iframe 中时,该方法返回嵌入窗口window.frameElement的元素(例如iframe或)。object否则,如果在顶级上下文中浏览,或者如果父框架和子框架具有不同的来源,它将评估为null.

window.frameElement
  ? 'embedded in iframe or object'
  : 'not embedded or cross-origin'

这是一个HTML 标准,在所有现代浏览器中都有基本支持。

于 2013-09-07T22:55:43.320 回答
29

RoBorg 是正确的,但我想补充一点。

在 IE7/IE8 中,当微软在他们的浏览器中添加选项卡时,他们破坏了一件事情,如果你不小心的话,这会对你的 JS 造成严重破坏。

想象一下这个页面布局:

MainPage.html
  IframedPage1.html   (named "foo")
  IframedPage2.html   (named "bar")
    IframedPage3.html (named "baz")

现在在“baz”框架中单击一个链接(没有目标,在“baz”框架中加载)它工作正常。

如果加载的页面,我们称之为 special.html,使用 JS 来检查“它”是否有一个名为“bar”的父框架,它将返回 true(预期)。

现在让我们说 special.html 页面在加载时检查父框架(是否存在及其名称,如果它是“bar”,它会在 bar 框架中重新加载自身。例如

if(window.parent && window.parent.name == 'bar'){
  window.parent.location = self.location;
}

到现在为止还挺好。现在出现了错误。

假设您不是像往常一样单击原始链接并在“baz”框架中加载 special.html 页面,而是单击它或选择在新选项卡中打开它。

当新标签加载时(根本没有父框架!IE 将进入无限循环的页面加载!因为 IE 在 JavaScript 中“复制”了框架结构,因此新标签确实有一个父标签,并且该父标签的名称为“bar”。

好消息是检查:

if(self == top){
  //this returns true!
}

在那个新选项卡中确实返回 true,因此您可以测试这种奇怪的情况。

于 2008-11-28T17:53:15.223 回答
28

我不确定这个示例如何适用于较旧的 Web 浏览器,但我将它用于 IE、Firefox 和 Chrome 没有问题:

var iFrameDetection = (window === window.parent) ? false : true;
于 2015-11-19T09:30:12.820 回答
19

在 Firefox 6.0 扩展(Addon-SDK 1.0)的内容脚本中,接受的答案对我不起作用:Firefox 在每个:顶级窗口和所有 iframe 中执行内容脚本。

在内容脚本中,我得到以下结果:

 (window !== window.top) : false 
 (window.self !== window.top) : true

这个输出的奇怪之处在于,无论代码是在 iframe 中还是在顶级窗口中运行,它总是相同的。

另一方面,谷歌浏览器似乎只在顶级窗口中执行我的内容脚本一次,所以上面的内容根本不起作用。

在两个浏览器的内容脚本中最终对我有用的是:

 console.log(window.frames.length + ':' + parent.frames.length);

如果没有 iframe 0:0,它会在包含一个框架的顶级窗口中打印1:1,并且在文档的唯一 iframe 中打印0:1

这允许我的扩展程序在两个浏览器中确定是否存在任何 iframe,另外在 Firefox 中确定它是否在其中一个 iframe 中运行。

于 2011-10-14T14:32:23.630 回答
16
if ( window !== window.parent ) 
{
      // The page is in an iframe   
} 
else 
{     
      // The page is not in an iframe   
}
于 2020-05-04T15:41:11.843 回答
5

我正在使用这个:

var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
于 2012-06-20T10:04:48.233 回答
2

使用这个 javascript 函数作为如何完成此操作的示例。

function isNoIframeOrIframeInMyHost() {
// Validation: it must be loaded as the top page, or if it is loaded in an iframe 
// then it must be embedded in my own domain.
// Info: IF top.location.href is not accessible THEN it is embedded in an iframe 
// and the domains are different.
var myresult = true;
try {
    var tophref = top.location.href;
    var tophostname = top.location.hostname.toString();
    var myhref = location.href;
    if (tophref === myhref) {
        myresult = true;
    } else if (tophostname !== "www.yourdomain.com") {
        myresult = false;
    }
} catch (error) { 
  // error is a permission error that top.location.href is not accessible 
  // (which means parent domain <> iframe domain)!
    myresult = false;
}
return myresult;
}
于 2011-09-21T02:32:51.913 回答
2

我实际上曾经检查 window.parent 并且它对我有用,但是最近 window 是一个循环对象,并且总是有一个父键,iframe 或没有 iframe。

正如评论所暗示的那样,很难与 window.parent 作品进行比较。如果 iframe 与父网页完全相同,则不确定这是否可行。

window === window.parent;
于 2014-03-04T03:47:39.027 回答
2

目前最好的旧版浏览器断帧脚本

其他解决方案对我不起作用。这个适用于所有浏览器:

防御点击劫持的一种方法是在每个不应加框的页面中包含一个“frame-breaker”脚本。即使在不支持 X-Frame-Options-Header 的旧版浏览器中,以下方法也可以防止网页被构图。

在文档 HEAD 元素中,添加以下内容:

<style id="antiClickjack">body{display:none !important;}</style>

首先将 ID 应用于样式元素本身:

<script type="text/javascript">
   if (self === top) {
       var antiClickjack = document.getElementById("antiClickjack");
       antiClickjack.parentNode.removeChild(antiClickjack);
   } else {
       top.location = self.location;
   }
</script>

这样,所有内容都可以在文档 HEAD 中,并且您的 API 中只需要一个方法/标签库。

参考:https ://www.codemagi.com/blog/post/194

于 2018-04-12T09:24:21.067 回答
1

由于您是在 facebook 应用程序的上下文中询问的,因此您可能需要考虑在发出初始请求时在服务器上检测到这一点。如果从 iframe 调用 Facebook 将传递一堆查询字符串数据,包括 fb_sig_user 键。

由于您可能需要在您的应用程序中检查和使用此数据,因此请使用它来确定要呈现的适当上下文。

于 2008-12-11T22:04:42.120 回答
0
function amiLoadedInIFrame() {
    try {
         // Introduce a new propery in window.top
         window.top.dummyAttribute = true;
         // If window.dummyAttribute is there.. then window and window.top are same intances
         return !window.dummyAttribute;
    } catch(e) {
         // Exception will be raised when the top is in different domain
         return true;
    }
}
于 2020-11-27T08:32:50.827 回答
0

按照@magnoz的说法,这是他的答案的代码实现。

constructor() {
    let windowLen = window.frames.length;
    let parentLen = parent.frames.length;

    if (windowLen == 0 && parentLen >= 1) {
        this.isInIframe = true
        console.log('Is in Iframe!')
    } else {
        console.log('Is in main window!')
    }
}
于 2020-12-20T16:04:12.630 回答
0
var inIFrame = window.location !== window.parent.location;
于 2022-02-17T17:15:44.677 回答
-2

这是我用过几次的古老代码:

if (parent.location.href == self.location.href) {
    window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468';
}
于 2011-10-25T03:57:35.517 回答
-2

如果您想知道用户是否从 facebook 页面选项卡或画布访问您的应用程序,请检查签名请求。如果你不明白,可能用户没有从 facebook 访问。确保确认 signed_request 字段结构和字段内容。

使用 php-sdk,您可以获得这样的签名请求:

$signed_request = $facebook->getSignedRequest();

您可以在此处阅读有关签名请求的更多信息:

https://developers.facebook.com/docs/reference/php/facebook-getSignedRequest/

和这里:

https://developers.facebook.com/docs/reference/login/signed-request/

于 2013-06-17T18:08:49.367 回答
-3

这对我来说是最简单的解决方案。

    <p id="demofsdfsdfs"></p>

<script>

if(window.self !== window.top) {

//run this code if in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "in frame";

}else{

//run code if not in an iframe
document.getElementById("demofsdfsdfs").innerHTML = "no frame";
}

</script>
于 2018-07-25T01:15:41.830 回答
-6
if (window.frames.length != parent.frames.length) { page loaded in iframe }

但前提是您的页面和在 iframe 中加载您的页面中的 iframe 数量不同。在您的页面中不设置 iframe 以 100% 保证此代码的结果

于 2012-10-27T15:31:39.323 回答
-6

在每个页面中编写此 javascript

if (self == top)
  { window.location = "Home.aspx"; }

然后它会自动重定向到主页。

于 2013-02-08T06:15:02.693 回答