“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.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沙箱,而不要将其与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