Использование JS, как я могу остановить дочерние iframes от перенаправления или, по крайней мере, запрашивать пользователей о перенаправлении

У многих сайтов есть скрипты, похожие на приведенные ниже. Они ставятся, чтобы остановить других людей от создания сайтов.

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

Мне нужно понять, что iframe пытается перенаправить, и если это так, я удалю iFrame и вместо этого поставлю ссылку на сайт. Таким образом, я не нарушаю политику использования созданного сайта, а также ссылку на сайт. Я понимаю, что вы можете использовать событие onbeforeunload, как обсуждалось здесь и здесь, но оба кажутся действительно неэтичными. Я помню, где-то читал о библиотеке, которая делает то же самое (digg делает то же самое). Любые вести?

Ответ 1

Проблема с вышеупомянутым решением заключается в том, что его можно удалить с помощью простого:

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/>";
}

Лучше всего решить эту проблему на стороне сервера (если можете). Если у вас есть доступ к серверу для веб-сайта, на котором будут храниться iframe, создайте промежуточное место прокси-сервера, где вы вытащите данные веб-сайта, а затем разделите теги script:

// 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, который может испортить, если не полностью лоботомизировать данный веб-сайт. Вам также необходимо убедиться, что все атрибуты src правильно изменены для узлов-потомков в HTML-сайте иностранного сайта.

С другой стороны, вы можете проверить свой серверный сайт и все его страницы JS, чтобы узнать, находится ли местоположение RegExp top (. | [\ s * ( "| ')) (это будет соответствовать top.location, top [" location и top ['location) существует (или если есть какие-либо ссылки на верхнюю часть), а затем используйте ссылку, если она существует, и собственно сайт, если это не так. Ущерб здесь заключается в том, что тогда вы вынуждаете пользователя ждать, пока вторичный сайт будет загружаться дважды - один раз на сервере и один раз в своем браузере. (если все не сделано через JS, но, на мой взгляд, это, как правило, более раздражает).

Лично я придерживаюсь мнения, что толпа "не кадрирует мой сайт" обычно может выиграть большинство битв, которая напрямую связана с iframe. С другой стороны, если код используется для обработки HTML, прежде чем он будет добавлен к веб-странице, тогда другая сторона будет больше, чем шанс для боя.



В качестве побочного примечания все это можно выполнить с помощью JavaScript и AJAX, но это, как правило, будет немного медленнее. Используйте сервер, если можете.

Ответ 2

Если вы используете HTML5, я бы предложил использовать новое свойство "песочницы", но он еще не совместим со всеми браузерами. http://www.w3schools.com/tags/att_iframe_sandbox.asp

В моем случае я просто добавил "allow-forms" и "allow-scripts" как значения свойств песочницы, а встроенный сайт больше не перенаправляет и все еще может запускать JavaScript

используя "allow-top-navigation", поскольку значение снова перенаправило сайт!

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

Если кто-нибудь знает какие-либо недостатки в использовании этого подхода, я хотел бы узнать об этом.

Кто-то другой с таким же ответом: fooobar.com/questions/54300/... (я натолкнулся на этот ответ позже)

Ответ 3

Вы можете попытаться создать фрейм-брейкер-баттер, все описано Джеффом Этвудом в его блоге: Мы сделали... Подставил! - 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)