2012-08-08 69 views
7

我可以限制字符串生成函數(使用函數構造函數)訪問父/全局作用域嗎?在Javascript中使用函數()創建沙箱

例如:下面的代碼按原樣打印false,因爲該函數正在窗口中存儲/修改變量a。

window.a = 4; 
Function("a=3;")() 
console.log(a === 4); 

我能限制訪問窗口/父範圍,並使其打印出「真」

回答

5

我不這麼認爲。使他們的影子他們,你能說出你想要的參數,以保護全局:

window.a = 4; 
Function("a", "a=3;")() 
console.log(a === 4); 

但功能將不得不進入全球不管你嘗試......這就是爲什麼它被稱爲全球。

根據你想要做的事情,還有其他的解決方法,比如網絡工作者......並且一如既往,hidden iframe hacks

+1

嗯,你可以定義'window'和'document'作爲參數,以防止直接訪問:無論是創建這樣的函數可以訪問iframe的全局範圍或頁面的全局範圍可以很容易地測他們(如你已經說過的),然後在代碼中加上''strict strict';'以防止全局變量的隱式定義。這可能會起作用。但是,只要不通過參數「遮蔽」它們,當然它並不妨礙對現有全局變量的訪問。也許可以迭代所有'window'屬性並自動創建參數列表。 – 2012-08-08 17:17:31

+0

@FelixKling聽起來不錯,我會嘗試一些黑客,看看我是否仍然可以訪問全球 – Esailija 2012-08-08 17:18:12

+0

@FelixKling這裏是我目前的一個,可以工作,如果你影「功能」http://jsfiddle.net/dFmyd/ – Esailija 2012-08-08 17:21:15

2

@ Esailija的回答是對的。另外,我建議首先限制你必須保護的全局變量的數量。放任何東西,你通常會放在全局命名空間中的APP範圍,你控制:

var APP = (function() { 
    return { 
     a: 4 
    }; 
}()); 

有沒有辦法完全限制訪問全球範圍內,但至少這種方式,你只需要保護一個對象:APP

9

這是一個額外的想法,與Esailija的建議一起可能非常強大(請參閱關於他的討論的評論)。

您可以創建虛擬iframe並使用其Function函數。使用它創建的函數默認情況下只能訪問iframe的範圍,儘管它仍然可以跳出它。幸運的是,通過Esailija的建議,很容易防止這種情況發生。

我能想象的功能是這樣的:

function sandboxed(code) { 
    var frame = document.createElement('iframe'); 
    document.body.appendChild(frame); 

    var F = frame.contentWindow.Function, 
     args = Object.keys(frame.contentWindow).join(); 

    document.body.removeChild(frame); 

    return F(args, code)(); 
} 

DEMO

可選方案,您可能要在前面加上'use strict';的代碼。


這至少在Chrome中起作用。

(function() { 
    var frame = document.createElement('iframe'); 
    document.body.appendChild(frame); 
    var same = window === frame.contentWindow.Function('return window;')(); 
    alert(same ? ':(' : ':)'); 
    document.body.removeChild(frame); 
}()); 
+1

非常有創意:D + 1我得到':)'除IE8之外,它拋出一個'不支持屬性或方法函數' – Esailija 2012-08-08 17:54:50

+0

@Esailija:謝謝測試(我沒有IE)。也許iframe的源代碼必須在IE中明確設置('frame.src ='about:blank''應該這樣做),或者該屬性的命名方式不同(不是'contentWindow')。如果你必須設置源代碼,也許你必須等待'load'事件才能訪問窗口,但是當然''sandboxed''接受回調的結果是沒有問題的:) – 2012-08-08 18:37:05

+0

是的,設置'frame .src'工程。 – Esailija 2012-08-08 18:45:50