Подтвердить что ты не робот

Безопасна ли техника "iframe sandbox"?

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

Теперь мой вопрос: работает ли описанная ниже техника * в современных браузерах и, в частности, кто-то может подтвердить, работает ли она в Safari?

Вот более поздний пост в блоге. В какой-то момент он говорит:

Песочницы-туземцы... поддерживаются в различных браузерах, в том числе... Safari 2.0 +

... но позже говорит, что метод iframe "поддерживается всеми главными браузерами, кроме Safari", и сделанный им резерв включает в себя выполнение некоторых странных вещей с фальшивыми конструкторами и __proto__, которые кажутся немного взломанными.

Мне почти трудно поверить, что два разных окна могут фактически использовать один и тот же, скажем, Object.prototype. Что происходит с междоменными iframe? Если я модифицирую прототипы в одном кадре, измените ли прототипы в другом кадре? Это кажется очевидной проблемой безопасности. Кто-то, пожалуйста, пролил свет на эту ситуацию.

* Под "work" я подразумеваю My.Object != Object, поэтому прототипы могут быть изменены в одном окне, не затрагивая другого.


Оригинальное сообщение

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

Вопрос заключается в том, как распространять собственные типы в javascript без фактического использования самих типов, поэтому просто изменить Array.prototype не стоит (может быть, другой код используется для... в массивах). Создание поддельного конструктора, возвращающего собственный массив с некоторыми функциями, на которые наложено, не похоже на хорошее решение, фактически расширение внутренних объектов кажется лучше. Но вы также не можете использовать обычное расширение для шаблона-оболочки прототипа javascript-функции с родными типами, потому что вы получите ошибки, такие как "push not generic", когда вы пытаетесь вызвать собственные функции.

Итак, решение, которое я имею в виду, работает следующим образом: создайте другое окно, добавьте функциональность в прототипы собственных конструкторов в этом окне и используйте эти конструкторы в своей программе.

Этот пример расширяет Array как My.Array с помощью функции each и String как My.String с помощью функции alert.

    var My = (function(){

      // create an iframe to get a separate global scope
      var iframe = document.createElement('iframe');
      iframe.style.height = '0px';
      iframe.style.width = '0px';
      iframe.style.border = 'none';
      iframe.style.position = 'absolute';
      iframe.style.left = '-99999px';
      document.documentElement.appendChild(iframe);
      var My = iframe.contentWindow;

      My.String.prototype.alert = function(){
        alert(this);
      }

      My.Array.prototype.each = function(callback){
        for (var i=0, l=this.length; i<l; i++) {
          callback(this[i], i);
        }
      }

      return My;

    }());

Опять же, мой вопрос заключается в том, обсуждался ли этот подход раньше, что он назвал, где я могу найти больше информации и т.д. Я хотел бы знать, есть ли более чистый способ получить другую глобальную область без использования iframe, или если это возможно, это по какой-то причине сбой в некоторых механизмах javascript, или если кто-то считает это особенно плохой идеей или что-то еще.


Обновление: я думаю, что люди называют этот вид iframe sandbox, чтобы не путать с атрибутом песочницы iframe HTML5.

связаны:

http://dean.edwards.name/weblog/2006/11/hooray/

http://webreflection.blogspot.com/2008/03/javascript-arrayobject.html

4b9b3361

Ответ 1

Я запустил эту страницу в разных браузерах (Safari, Opera, IE7-9, Chrome, Firefox) и получил согласованные результаты со всем, кроме firefox, в firefox прототипы изолированы, так что хороший, но второй тест по какой- Fire Fox. Прототип iframe не сразу дополняется. Но это не имеет значения, если вы все равно не хотели его дополнять. Вы можете попробовать запустить его в большинстве браузеров для тестирования.

Обратите внимание, что это действительно не проверяет какие-либо из причуд, например (My.Array().slice будет возвращать основные массивы window в зависимости от браузера...), и их может быть больше. Поэтому я бы сказал, что это довольно опасно.

В любом случае это перебор, и он слишком много работает без реального выигрыша.

<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
(function(){
    var ifr = document.createElement("iframe"),
        callbacks = [],
        hasReadyState = "readyState" in ifr;

    ifr.style.display = "none";


    document.body.appendChild(ifr);
    ifrDoc = ifr.contentWindow.document;
    ifrDoc.open();
    ifrDoc.write( "<!DOCTYPE html><html><head></head><body>"+"<"+"script"+">var w = this;"+"</"+"script"+">"+"</body></html>");
    ifrDoc.close();

    if( hasReadyState ) {

        ifr.onreadystatechange = function(){
            if( this.readyState === "complete" ) {
                fireCallbacks();
            }
        };

    }

    function fireCallbacks(){
        var i, l = callbacks.length;
        window.My = ifr.contentWindow.w;

        for( i = 0; i < l; ++i ) {
            callbacks[i]();
        }

        callbacks.length = 0;


    }

    function checkReady(){

        if( hasReadyState && ifr.readyState === "complete" ) {
        fireCallbacks();
        }
        else if( !hasReadyState ) {
        fireCallbacks();
        }
    }

    window.MyReady = function(fn){
        if( typeof fn == "function" ) {
            callbacks.push( fn );
        }
    };


window.onload = checkReady; //Change this to DOMReady or whatever
})()


MyReady( function(){

    My.Object.prototype.test = "hi";

    var a = new My.Object(),
        b = new Object();

    console.log( Math.random(), My.Object !== Object && b.test !== "hi", a.test === "hi" );

});
</script>

</body>
</html>

Ответ 2

Если у вас есть два разных фрейма с содержимым, загруженным из разных доменов, то ни один современный браузер не сможет взаимодействовать на уровне JavaScript между ними по очевидным соображениям безопасности. Лучше всего было бы настроить тест и посмотреть, что произойдет для себя, но я уверен, что то, что вы описываете, должно быть безопасным для большинства браузеров.