vm
vm是node的一個核心模組,核心功能官方文件介紹是:
The vm module provides APIs for compiling and running code within V8 Virtual Machine contexts. The vm module is not a security mechanism. Do not use it to run untrusted code. The term “sandbox” is used throughout these docs simply to refer to a separate context, and does not confer any security guarantees.
意思就是:vm可以使用v8的Virtual Machine contexts動態地編譯和執行程式碼,而程式碼的執行上下文是與當前程式隔離的,但是這裡的隔離並不是絕對的安全,不完全等同瀏覽器的沙箱環境。
例子
vm的使用很簡單,下面是幾個例子:
-
vm.runInNewContext
const vm = require(`vm`); const sandbox = { a: 1 }; // 在新的上下文執行 const result = vm.runInNewContext(`a += 1`, sandbox); console.log(result);// 2 console.log(sandbox);// { a: 2 }
-
vm.runInContext
const vm = require(`vm`); const sandbox = { a: 1 }; // https://nodejs.org/api/vm.html#vm_what_does_it_mean_to_contextify_an_object vm.createContext(sandbox); // 在執行上下文執行 const result = vm.runInContext(`a += 1`, sandbox); console.log(result);// 2 console.log(sandbox);// { a: 2 }
-
vm.runInThisContext
const vm = require(`vm`); global.a = 1; // 在當前上下文執行 vm.runInThisContext(`a += 1`); console.log(global.a);// 2
使用場景
我個人理解vm的使用場景有2個:
- 環境隔離:
因為node的js程式碼是單執行緒,在併發的場景下,需要考慮上下文的競爭和互相影響,直接使用vm,可以最小成本的解決這個問題。
vue ssr在2.3.0以前,就是用vm來做隔離的渲染的,但是也帶來了效能的問題,具體可以檢視文件的介紹。
- 動態執行字串程式碼:
這在某些需求場景下只能使用vm。
劣勢
vm也有明顯的劣勢:
- 耗費資源:
這裡有文章比較
eval
和vm
的效能:https://odino.org/eval-no-more-understanding-vm-vm2-nodejs/。(當然eval的安全問題更大,這是另外的話題)。 - maybe attacked
vm也存在安全問題,對於執行外部的程式碼,可能引發安全問題。
所以有個開源庫專門解決了這個問題,https://github.com/patriksimek/vm2,宣告已經過濾了所有已知攻擊。