Безопасна ли техника «песочницы iframe»? - PullRequest
17 голосов
/ 08 декабря 2011

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

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

Вот более свежее сообщение в блоге .В какой-то момент написано:

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

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

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

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


Оригинальный пост

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

Вопрос в том, как расширить нативные типы в javascript, фактически не связываясь с самими типами, поэтому просто изменив массив.Прототип не годится (возможно, другой код использует for ..in с массивами).Создание фальшивого конструктора, который возвращает собственный массив с некоторыми привязанными функциями, тоже не кажется хорошим решением, фактически расширение собственных объектов кажется более подходящим.Но вы не можете сделать обычное расширение стиля переключателя для прототипа фиктивной функции javascript с нативными типами, потому что вы будете получать ошибки типа «push не является универсальным» при попытке вызвать нативные функции.

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

В этом примере Array расширяется до My.Array с помощьюeach function и String as 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, или если кто-то считает, что это особенно плохая идеяили что-то еще.


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

относящиеся:

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

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

Ответы [ 2 ]

6 голосов
/ 15 декабря 2011

Я запустил эту страницу в различных браузерах (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>
1 голос
/ 13 декабря 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...