1 回答

TA貢獻1851條經驗 獲得超4個贊
所有,我能想到的是將腳本包裝在它自己的函數中,就像 nodejs 已經為 commonJS 模塊所做的那樣。這是常規包裝。
(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});
如果您使用自己的包裝器包裝該用戶代碼,然后當您調用它來執行它時,您可以為 和任何其他半全局符號定義您自己的require值module。
如果你也把'use strict'; 作為包裝函數的第一行(在任何用戶代碼之前),那么這將消除對global對象的默認分配,x = 4因為如果沒有首先明確定義,這將是一個錯誤x。如果您隨后還創建自己的全局對象并將其作為參數傳遞,則可以防止任何人分配給真正的全局對象。我認為您不能阻止對預先存在的全局變量的隱式讀取訪問。
因此,您的包裝器可能如下所示:
(function(exports, require, module, __filename, __dirname, global) {
'use strict';
// insert user code here before evaluating it with eval()
// and getting the function which you can then call and pass the desired arguments
});
然后,當你調用這個函數時,你把你想要的所有參數的值傳遞給它(不是真實的)。
請注意,很難說這種方案的防漏性能到底如何。任何真正的安全都應該在資源受限的虛擬機中運行。
另一個想法,您可以在具有自己的原始全局變量集的工作線程中運行。因此,您完成上述所有操作并在工作線程中運行它。
在評論中解決您的問題:
是否“使用嚴格”;需要進入包裝函數內部還是外部?
它必須是包裝函數內的第一行代碼,就在您插入用戶代碼的位置之前。這個想法是強制該包裝器內的功能范圍(用戶代碼所在的位置)處于嚴格模式,以限制它可以做的一些事情。
你能解釋一下“我認為你不能阻止對預先存在的全局變量的隱式讀取訪問。”嗎?如果我將自己的對象作為全局對象提供,內部腳本如何訪問預先存在的全局對象?
global任何代碼,甚至是嚴格模式代碼都可以在沒有前綴的情況下訪問預先存在的全局變量。雖然您可以通過在包裝函數參數中使用您自己的遮蔽它global并強制它進入嚴格模式來阻止代碼創建新的全局變量,但您不能阻止嚴格模式代碼讀取現有的全局變量,因為它們可以在沒有全局前綴的情況下這樣做. 因此,如果有一個預先存在的名為“foo”的全局變量,那么現有代碼可以像這樣引用它:
console.log(foo);
或者
foo = 12;
如果foo在更近的范圍內沒有,解釋器將foo在全局對象上找到并使用它。
請注意,嚴格模式會阻止自動創建新的全局,例如:
greeting = "happy birthday"
您能否詳細說明沒有“資源受限的虛擬機”?
我說的是真正的硬件/操作系統級別的虛擬機,它們允許您完全控制進程可能使用的資源(磁盤訪問、套接字、內存、硬件等)。它本質上是一個與同一系統上的任何其他 VM 分開的虛擬計算機環境。這是一個更嚴格的控制水平。
WorkerThread 是一個非常有趣的概念。會看看!我的理解是 WorkerThreads 提供內存隔離,共享數據的唯一方法是發送消息(有效地創建副本)?
是的,工作線程提供了很好的隔離,因為它們啟動了一個全新的 JS 引擎并擁有自己的全局變量。它們可以以某種方式共享 ArrayBuffers(如果你選擇這樣做的話),但是普通的 JS 變量不能跨線程邊界訪問。它們通常會通過消息傳遞(通過事件隊列自動同步)進行通信,但如果需要,您也可以通過套接字進行通信。
添加回答
舉報