"iframe沙箱"技术安全吗?

Dag*_*bit 17 javascript safari iframe constructor

更新:由于没有答案,我正在稍微改变这个问题.以下链接在Dean的博客上的帖子的评论表明这种技术在Safari中不起作用.

我现在的问题是:下面描述的技术在现代浏览器中是否有效*,特别是有人可以确认它是否适用于Safari?

这是一篇更新的博客文章.它曾经说过:

Sandboxed natives ...在各种浏览器中都受支持,包括...... Safari 2.0+

...但后来说iframe技术"除了Safari之外的所有主流浏览器都支持",而且他所展示的后备涉及使用伪造的构造函数做一些奇怪的事情,而且__proto__看起来有点hacky.

我几乎发现很难相信两个不同的窗口实际上可以共享相同的内容,例如Object.prototype.跨域iframe会发生什么?如果我在一帧中修改原型,那么另一帧中的原型是否会被修改?这似乎是一个明显的安全问题.有人请说明这种情况.

*我的意思是"工作" My.Object != Object,所以可以在一个窗口中修改原型而不影响另一个窗口.


原帖

我知道之前已经问过这个问题,但我有一个特定的解决方案,我想知道这种解决方案之前是否已经讨论过,我想知道它是多么可靠和被广泛接受.

问题是如何在javascript中扩展本机类型而不会实际上弄乱类型本身,所以只是改变Array.prototype是不好的(也许其他代码使用for..in与数组).创建一个返回带有某些函数的本机数组的伪构造函数似乎也不是一个好的解决方案,实际上扩展本机对象似乎更好.但你不能用原生类型做正常的javascript虚函数原型switcharoo样式扩展,因为当你试图调用本机函数时,你会得到像"push is not generic"这样的错误.

所以,我想到的解决方案是这样的:创建另一个窗口,在该窗口中向原生构造函数的原型添加功能,并在程序中使用这些构造函数.

此示例扩展ArrayMy.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;

    }());
Run Code Online (Sandbox Code Playgroud)

同样,我的问题是这种方法之前是否已被讨论,它被称为什么,我可以在哪里找到更多信息等等.我想知道是否有更简洁的方法来获得另一个全局范围而不使用iframe,或者如果在某些javascript引擎中,或者如果有人认为这是一个特别糟糕的想法或其他原因,这可能会因某种原因而失败.


更新:我猜人们将这种东西称为iframe沙箱,不要与HTML5 iframe沙箱属性混淆.

有关:

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

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

Esa*_*ija 6

我在各种浏览器(Safari,Opera,IE7-9,Chrome,Firefox)中运行此页面并获得了一致的结果,除了firefox,在firefox中原型是沙箱,所以这很好,但第二次测试由于某种原因在firefox中失败.iframe原型不会立即增加.但是如果你不打算无论如何都要增加它并不重要.您可以尝试在更多浏览器中运行它来进行测试.

请注意,这并没有真正测试任何怪癖(例如,My.Array().slicewindow根据浏览器返回主数组......)并且可能会有更多.所以我会说这很不安全.

无论如何这都是一种矫枉过正的事情,似乎太多的工作没有真正的收获.

<!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>
Run Code Online (Sandbox Code Playgroud)