代码之家  ›  专栏  ›  技术社区  ›  Ritesh M Nayak beny23

使用JS如何阻止子iframes重定向,或者至少提示用户有关重定向的信息

  •  14
  • Ritesh M Nayak beny23  · 技术社区  · 15 年前

    许多网站都有与下面类似的脚本。这样做是为了阻止其他人在网站上设置框架。

    if (top.location != location) {
      top.location.href = document.location.href;
    }
    

    我需要一些方法来认识到iframe正在尝试重定向,如果是,我将删除iframe,并改为放置一个指向该站点的链接。这样,我就不会违反框架网站的使用策略,也不会链接到该网站。我了解您可以使用讨论过的OnBeforeUnload事件 here here 但这两个看起来都不道德。我记得在某个地方读到过一个图书馆,它做着完全相同的事情(Digg做着同样的事情)。有什么线索吗?

    3 回复  |  直到 11 年前
        1
  •  16
  •   cwallenpoole    15 年前

    上述解决方案的问题在于,可以使用简单的:

    if( top != self )
        delete top.onbeforeunload;
    

    一旦被召唤,那么 prevent_bust 将永远不会增加,这意味着网站将免费重新定向没有您的同意或知识。糟糕的交易。

    如果您想要该解决方案的一致功能版本,我建议您改为这样做:

    // Create a random seed value, making it almost impossible to 
    // determine what is being tested for.
    var prevent_bust = Math.random() * 3000; 
    
    // enclose everything in a function, so that it cannot be addressed
    function iniFunc ( init ) { 
        // The function is no longer in scope of the main window.
        function onbeforeunload() { prevent_bust++ }
        window.onbeforeunload = onbeforeunload;
        setInterval( function() {
            // make sure the function was not deleted.
            if( window.onbeforeunload != onbeforeunload )
            {
                prevent_bust = init + 1;
                window.onbeforeunload = onbeforeunload;
            }
            if (prevent_bust > init ) {  // All comparison is to the random seed.
                prevent_bust -= 2
                window.top.location = 'http://server-which-responds-with-204.com/' 
                // Unfortunately, you have absolutely no idea which website caused
                // the incrementation, so you cannot replace it with a link!
                //
                // You might try to simply ignore it and just use the iframe as is -- 
                // theoretically, they are no longer able to bust this frame. 
                // (this theory will be disproved below).
           }
       }, 1 );
    };
    iniFunc( prevent_bust );
    

    不幸的是,这确实会导致留下一个问题——检索已设置的间隔、取消设置间隔,然后重新定向页面是一件微不足道的事情:

    // setTimeout will return the highest timeout which is not "in use", in this case,
    // it will be the original setInterval (from the above function) + 1.
    // Event if there are 1,000 intervals already set, it will be rather trivial to 
    // clear them all.
    var currentInterval = 10000;
    // window.setTimeout( gotoHREF, 100 );
    
    // clearInterval will not interfere with setTimeout, so we can clear all
    // of the Intervals already set.
    for( var i = 0; i < currentInterval; i++ ) top.clearInterval( i );
    
    function gotoHREF(){
        top.location.href = "http://<my-url/>";
    }
    

    您最好的选择实际上是在服务器端解决这个问题(如果可以的话)。如果您有权访问将保存iframes的网站服务器,请创建一个临时代理位置,从中提取网站数据,然后删除脚本标记:

    // In php
    $dd = new DOMDocument();
    // file_get_contents will simply convert the entire web address into a String
    $dd->loadXML( file_get_contents( "http://" . $_GET[ 'loadedURL' ] ) );
    $scripts = $dd->getElementsByTagName( "script" );
    
    // iterate through the website and remove all script tags.
    for( $i = 0; $i < $scripts->length; $i++ )
    {
        $current = $scripts->item( $i );
        $current->parentNode->removeChild( $current );
    }
    
    // output it to the dummy page.
    echo $dd->saveXML();
    

    然后您将使用标签:

    <iframe src="redirect.php?loadedURL=http://www.google.com"></iframe>
    

    不幸的是,这意味着您的iframe将在没有javascript的情况下运行,如果不完全将所讨论的网站分块的话,它可能会损坏。您还需要确保为外部站点的HTML中的后代节点正确修改了所有SRC属性。

    另一方面,您可以让您的服务器检查框架站点及其所有JS页面,以查看regexp top(.[\s*(“”)位置(这将匹配top.location、top[”location和top[”location)是否存在(或者是否存在对top的任何引用),然后使用链接(如果存在)以及站点是否正确(如果不存在)。这样做的不利之处在于,您强迫用户等待辅助站点加载两次——一次在服务器上,一次在浏览器中。(除非一切都是通过JS完成的,但在我看来,这通常更烦人)。

    就我个人而言,我认为“不构建我的站点”的人群通常可以赢得大多数直接涉及i frame的战斗。另一方面,如果在将HTML附加到网页之前使用代码来处理HTML,那么另一方就不只是一个战斗的机会。



    附带说明的是,所有这些都可以通过JavaScript和Ajax完成,但通常会慢一点。如果可以的话,使用服务器。

        2
  •  6
  •   Community Romance    7 年前

    如果您使用的是HTML5,我建议您使用新的“沙盒”属性,但它还不能与所有浏览器兼容。 http://www.w3schools.com/tags/att_iframe_sandbox.asp

    在我的例子中,我只是添加了“allow forms”和“allow scripts”作为沙盒属性值,嵌入的站点不再重定向,仍然可以运行javascript。

    使用“允许顶部导航”作为值使网站再次重定向!

    前任: <iframe sandbox="allow-forms allow-scripts" ... /></iframe>

    如果有人知道使用这种方法的任何缺点,我很想知道。

    有相同答案的其他人: https://stackoverflow.com/a/9880360/1404129 (我后来偶然发现这个答案)

        3
  •  3
  •   MBO    15 年前

    你可以试着创造一个框克星巴斯特,一切都是由杰夫阿特伍德在他的博客中描述的: We Done Been ... Framed! - coddinghorror.com

    简言之,您应该实现如下内容:

    var prevent_bust = 0  
    window.onbeforeunload = function() { prevent_bust++ }  
    setInterval(function() {  
      if (prevent_bust > 0) {  
        prevent_bust -= 2
        window.top.location = 'http://server-which-responds-with-204.com' 
        // replace your iframe with link to it
      }  
    }, 1)