检测此页面是不是在跨域 iframe 内部的万无一失的方法

Posted

技术标签:

【中文标题】检测此页面是不是在跨域 iframe 内部的万无一失的方法【英文标题】:Foolproof way to detect if this page is INSIDE a cross-domain iframe检测此页面是否在跨域 iframe 内部的万无一失的方法 【发布时间】:2014-03-12 03:53:51 【问题描述】:

对“Foolproof way to detect if iframe is cross domain”的回答描述了一种测试页面上的 iframe 是否指向同域或跨域页面的方法,解决不同浏览器对跨域策略的解释并避免错误消息这会打断用户或停止 javascript

我希望做与此等效的操作,但 from iframe 内的子页面测试它是否 inside 是跨域 iframe。

access (same domain) info about the parent 可以使用 parent 全局,例如parent.document.location,但是当它检测到父级是跨域时,是否有一种可靠的方法来执行此跨浏览器而不会崩溃


为了方便测试,这是jsfiddle 中的jsbin,在尝试测试parent.location.host 是否可访问时会崩溃并出错。有没有可靠的方法来获得可用的东西,比如false,告诉我们这是一个跨域父级,而不是一个错误?

是否有一个try...catch 变体将是强大的跨浏览器?或者可能是使用来自parent.postMessage() 的返回值的一些巧妙技巧? (虽然不能编辑父页面)


用例:想象一下可嵌入内容,这些内容要嵌入到自己网站的页面上,也可以由第三方嵌入。如果页面位于同域 iframe 上,我们会隐藏品牌并链接回原始站点,因为用户已经在这里。如果他们从第 3 方 iframe 访问页面或直接加载页面,我们会显示品牌和信用,以便他们可以看到内容的来源。


澄清一下,我知道同域策略,我不关心跨浏览器域是什么,我只是想写一个简单但可靠的if 条件,例如if( crossDomainParent() ) /* do something */

【问题讨论】:

相关:Access parent URL from iframe 我见过的最佳答案是访问 try-catch 中的 top.document ***.com/a/19566486/151503 【参考方案1】:

我尝试使用引荐来源网址来确定跨域,但我发现它在许多网站上都不可靠。也许有人会觉得这很有用。

function IsCrossDomainFrame() 
    if( parent === window ) return false; //not a frame
    var parentLocation = new URL(document.referrer);//the referrer of an iframe is the parent
    return (parentLocation.protocol !== location.protocol ||
            parentLocation.hostname !== location.hostname ||
            parentLocation.port     !== location.port);

协议、主机名和端口决定跨域。

【讨论】:

请修正“document.referer”中的错字,它应该是“document.referrer”(双r)。除此之外,从我目前的测试来看,这似乎是一个非常好的解决方案。【参考方案2】:

真正的跨浏览器解决方案:

function isCrossOriginFrame() 
  try 
    return (!window.top.location.hostname);
   catch (e) 
    return true;
  


console.log(isCrossOriginFrame());

在相当多的桌面和移动浏览器上进行了测试。

https://jsfiddle.net/arzd4btc/3/

【讨论】:

Thx @JeffMixon,我稍微改了一下,改为:function isCrossOriginFrame() try return (document.location.hostname !== window.parent.location.hostname); 捕捉 (e) 返回真; 【参考方案3】:

对于嵌套 iframe:一种递归方式来了解 iframe(执行此代码的位置)是否跨域:

function crosDomIfrm(win, data) 
        data = (typeof data === 'undefined')?ref:win.document.location,isCD:false:data;
        try  
            if( win.document.referrer != '' )
                data.isCD = parseURL(data.ref) != parseURL(win.document.referrer);
            
         catch(e)
        if ( (win.self !== win.parent) && !data.isCD )  //I'm in iframe
            data = crosDomIfrm( win.parent, data );
        
        return ref:data.ref,isCD:data.isCD;
    ,

function parseURL(url) 
                var a=document.createElement('a');
                a.href=url;
                return a.hostname;
            

【讨论】:

【参考方案4】:

如果我看到你的用例:

我会使用 $_SERVER['REMOTE_ADDR'] 检查服务器端(谁调用了您的网站),如果它是您的 IP,那么您可以隐藏品牌和链接。

如果用例将阻止您的网站框架,您可以使用X-Frame-Options: deny

其他猜测: 文档中的元素有一个ownerDocument 属性,也许这可以帮助检测你想要什么。

【讨论】:

有趣的想法,但不幸的是我无法在这个项目中更改服务器端代码。我研究了使用 javascript 获取 HTTP 标头的可能性,虽然 it is possible to get some HTTP header data client-side using new XMLHttpRequest();,但它不包含在这种情况下有用的数据。【参考方案5】:

试试这个(在 iframe 中)

<script type="text/javascript">
  var detectOrigin = (window.location.ancestorOrigins === undefined ? 
  /example.com/.test(document.domain) /* firefox */ : 
  /example.com/.test(window.location.ancestorOrigins[0])); /* webkit */
  if (detectOrigin === true) console.log(detectOrigin); /* `true` example.com origin */
  if (detectOrigin === false) console.log(detectOrigin); /* `false` !example.com origin */
</script>

【讨论】:

【参考方案6】:

使用 x-frame 标头,这将防止将您的网站加载到 frame/iframe 。有多种选择read here

【讨论】:

这将使浏览器在 iframe 中显示错误,而不是在您的网站中显示错误,也就是说,您将完全失去 iframe 流量,而不是跳出 iframe。【参考方案7】:

首先检查你是否是 IFramed。

window.self !== window.top

如果您是 IFramed,那么您的推荐人就是您的父框架 url。

document.referrer

从这个 url 你应该能够检测到你是否想要分支你的代码。

【讨论】:

有趣的想法,+1。到目前为止,我只做了一点跨浏览器测试,但基于此,您确实可以安全地检查document.referrer,首先检查它不是一个空字符串(如果它没有在 Firefox 中加框,它将是)然后解析它以获取域。目前无法测试 IE,稍后再试。使用jsfiddle.net/Ke3Z6/4 和jsbin.com/loyuy/10/edit document.referrer 仅在框架页面没有导航到任何地方时才有效!一旦发生这种情况,referrer 就会成为上一个框架页面。 好点 - 幸运的是,框架内容是您可以控制的内容,因此可以确保页面无法导航。 referrer 不是一个可靠的值,它可以被停用、伪造,并且在某些情况下不按要求发送,例如当referrer 是 HTTPS 和目标 HTTP 时。它应该适用于您的用例想法,但我不会对此太有信心。一种正确的方法是管理 2 个 URL,一个没有品牌但返回 HTTP 标头 X-FrameOptions 作为 SAMEORIGIN,另一个有品牌但没有此标头。 可以通过检查父窗口是否 === 来解决 chrome 中的问题。这当然不能在弹出窗口中进行准确的检查。【参考方案8】:

根据您当前的限制,无法使用 DOM API 实现此目的。任何带有属于另一个域的窗口的评估都会抛出一个错误。

但是,“黑客”是从您的子窗口发送 XHR 以加载您域中的已知页面。如果这个 XHR 成功完成,那么你就知道两个窗口是同一个域。

但是,这会将错误消息记录到控制台。

【讨论】:

以上是关于检测此页面是不是在跨域 iframe 内部的万无一失的方法的主要内容,如果未能解决你的问题,请参考以下文章

如何将焦点设置在跨域的 iframe 上

如何在跨域中获取 iframe contentWindow 高度

iframe跨域获取父页面url

postMessage处理iframe 跨域问题

postMessage处理iframe 跨域问题

跨域方式