node核心模組-vm

keller35發表於2019-02-16

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的使用很簡單,下面是幾個例子:

  1. 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 }
  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 }
  3. vm.runInThisContext

    const vm = require(`vm`);
        
    global.a = 1;
    // 在當前上下文執行
    vm.runInThisContext(`a += 1`);
    console.log(global.a);// 2

使用場景

我個人理解vm的使用場景有2個:

  1. 環境隔離:

    因為node的js程式碼是單執行緒,在併發的場景下,需要考慮上下文的競爭和互相影響,直接使用vm,可以最小成本的解決這個問題。

    vue ssr在2.3.0以前,就是用vm來做隔離的渲染的,但是也帶來了效能的問題,具體可以檢視文件的介紹。

  2. 動態執行字串程式碼:

    這在某些需求場景下只能使用vm。

劣勢

vm也有明顯的劣勢:

  1. 耗費資源:

    這裡有文章比較evalvm的效能:https://odino.org/eval-no-more-understanding-vm-vm2-nodejs/。(當然eval的安全問題更大,這是另外的話題)。

  2. maybe attacked

    vm也存在安全問題,對於執行外部的程式碼,可能引發安全問題。

    所以有個開源庫專門解決了這個問題,https://github.com/patriksimek/vm2,宣告已經過濾了所有已知攻擊。

相關文章