“iframe沙箱”技术是否安全?

更新:由于这是没有答案,我稍微改变了这个问题。 关于下面链接的Dean博客文章的评论表明这种技术在Safari中不起作用。

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

这是最近的博客文章。 它有一点说:

沙盒版本地......在各种浏览器中都受支持,包括... Safari 2.0+

......但后来他说iframe技术“得到了除Safari之外的所有主流浏览器的支持”,并且他展示的后备方案涉及到用伪造的构造函数和__proto__来做一些奇怪的事情,这看起来有点怪异。

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

*通过“工作”我的意思是My.Object != Object ,所以原型可以在一个窗口中修改而不会影响其他。


原帖

我知道这个问题以前已经被问到过,但我有一个特定的解决方案,我想知道这种解决方案是否已经在之前讨论过,以及在哪里我可以学习它的可靠性和广泛接受度。

问题是如何在JavaScript中扩展本地类型而不真正搞乱类型本身,所以只是改变Array.prototype是不好的(也许其他代码使用for..in与数组)。 创建一个假的构造函数,返回一个本地数组并附带一些函数,似乎也不是一个好的解决方案,实际上扩展本地对象似乎更好。 但是你不能用原生类型来做普通的JavaScript虚拟函数原型switcharoo风格的扩展,因为当你尝试调用本机函数时,你会遇到像“push is not generic”这样的错误。

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

此示例将Array作为My.Arrayeach函数一起使用,将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沙箱,而不要将其与HTML5 iframe沙盒属性混淆。

有关:

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

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


我在不同的浏览器(Safari,Opera,IE7-9,Chrome,Firefox)上运行了这个页面,并且在firefox中获得了一致的结果,在firefox中,原型被沙箱化,所以很好,但是第二个测试由于某种原因在Firefox中失败了。 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>

如果您有两个不同的框架,内容是从不同的域加载的,那么现代浏览器就不允许在它们之间的JavaScript级别上进行任何交互,这是出于明显的安全原因。 当然,你最好的选择是设置一个测试,看看你自己会发生什么,但我很确定你所描述的内容在大多数浏览器上都应该是安全的。

链接地址: http://www.djcxy.com/p/18337.html

上一篇: Is the "iframe sandbox" technique safe?

下一篇: Javascript for Div height, make it faster