2011-12-08 184 views
17

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

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

这是最近的blog post。它说,在一个点上:

沙盒当地人......在各种浏览器,包括支持... Safari浏览器2.0+

...但后来说的iframe技术“受到除Safari之外的所有主流浏览器的支持“,而他所展示的后备功能涉及到使用伪造的构造函数做出一些奇怪的事情,并且似乎有点冒失。

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

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


原帖

我知道这已经被问过,但我心里有一个具体的解决方案,我想知道,如果这类型的解决方案已经讨论之前,我可能会学到它的可靠性和广泛接受度。

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

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

此示例Array作为My.Arrayeach功能和作为StringMy.Stringalert功能延伸。

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

+0

得到一个干净的窗口对象是合法使用iframe,虽然这种技术最常用的为*获得的这些额外的方法摆脱*然后将它们添加... – hugomg

+0

missingno,知道任何事情目前使用这种技术?它有一些奇怪的分支,我想如果它正在被使用,必须有一些关于它的邮件列表讨论 –

+3

我记得读过[presentation](http://www.slideshare.net/benvinegar/modern-iframe-programming -8281214)来自Disqus的一个人。他们使用这种技巧,因为他们需要能够在任何地方嵌入代码。 – hugomg

回答

6

我在各种浏览器(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> 
+1

标记正确。毕竟,我已经决定不做iframe沙箱事情了,原因很多。 –

1

如果您有来自不同域加载内容的两个不同的帧,然后没有现代的浏览器将允许它们之间的JavaScript的水平明显安全的任何互动原因。当然,你最好的选择是设置一个测试,看看你自己会发生什么,但我很确定你所描述的内容在大多数浏览器上都应该是安全的。

+0

是的,但我没有一个mac。真的,我只需要有人为我测试它。另外,我想知道是否可以通过在不同的子域中启动iframe并在之后更改document.domain来伪造它。 –

+0

啊,好吧,是的,我也没有Mac。我会说在IE,FireFox和Chrome中试用它。如果它通过所有三个,我会说你很好去。您可以随时找人在Safari中测试它,但我认为它不应该成为您的阻塞优先级。当然,如果你真的想,你可以在VirtualBox中设置一个MacOS实例.... –