我正在编写基于iframe的脸书应用。现在我想使用相同的html页面来呈现普通网站以及facebook中的画布页面。我想知道我是否可以确定页面是在iframe中加载还是直接在浏览器中加载?
答案 0 :(得分:970)
由于same origin policy,浏览器可能会阻止对window.top
的访问。 IE漏洞也会发生。这是工作代码:
function inIframe () {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
top
和self
都是window
个对象(以及parent
),因此您可以看到您的窗口是否是顶部窗口。
答案 1 :(得分:78)
当在与父级相同的原点的iframe中时,window.frameElement
方法会返回嵌入窗口的元素(例如iframe
或object
)。否则,如果在顶级上下文中浏览,或者父框架和子框架具有不同的来源,则评估为null
。
window.frameElement
? 'embedded in iframe or object'
: 'not embedded or cross-origin'
这是HTML Standard,在所有现代浏览器中都有基本支持。
答案 2 :(得分:25)
RoBorg是正确的,但我想添加旁注。
在IE7 / IE8中,当微软将Tabs添加到他们的浏览器时,如果你不小心,他们就会破坏一件会对你的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”,它会在条形框架中重新加载。例如
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,因此您可以测试这个奇怪的条件。
答案 3 :(得分:18)
在Firefox 6.0 Extension(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中运行。
答案 4 :(得分:7)
我不确定此示例如何适用于较旧的Web浏览器,但我将其用于IE,Firefox和Chrome而没有问题:
var iFrameDetection = (window === window.parent) ? false : true;
答案 5 :(得分:5)
我正在使用它:
var isIframe = (self.frameElement && (self.frameElement+"").indexOf("HTMLIFrameElement") > -1);
答案 6 :(得分:5)
if ( window.location !== window.parent.location )
{
// The page is in an iframe
}
else
{
// The page is not in an iframe
}
答案 7 :(得分: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;
}
答案 8 :(得分:1)
由于您在Facebook应用程序的上下文中询问,您可能需要考虑在初始请求发生时在服务器上检测到此问题。 Facebook将传递一堆查询字符串数据,包括fb_sig_user密钥,如果它是从iframe调用的。
由于您可能需要在应用中检查并使用此数据,因此请使用它来确定要呈现的相应上下文。
答案 9 :(得分:1)
我实际上用来检查window.parent它对我有用,但最近窗口是一个循环对象,并且总是有一个父键,iframe或没有iframe。
由于评论建议与window.parent相比很难。如果iframe与父网页完全相同,则不确定这是否有效。
window === window.parent;
答案 10 :(得分:1)
其他解决方案对我没用。这适用于所有浏览器:
防止点击劫持的一种方法是在每个页面中包含一个不应框架的“框架破坏”脚本。即使在不支持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中只需要一个方法/ taglib。
答案 11 :(得分: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!')
}
}
答案 12 :(得分: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;
}
}
答案 13 :(得分:0)
这对我来说是最简单的解决方案。
<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>
答案 14 :(得分:-1)
如果您想知道用户是否从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/
答案 15 :(得分:-1)
这是我用了几次的古代代码:
if (parent.location.href == self.location.href) {
window.location.href = 'https://www.facebook.com/pagename?v=app_1357902468';
}
答案 16 :(得分:-4)
在每个页面中写这个javascript
if (self == top)
{ window.location = "Home.aspx"; }
然后它会自动重定向到主页。
答案 17 :(得分:-4)
if (window.frames.length != parent.frames.length) { page loaded in iframe }
但是,只有当您的页面和网页中的iframe数量与iframe中加载时不同时才会出现问题。在页面中不使用iframe以100%保证此代码的结果