共计 1337 个字符,预计需要花费 4 分钟才能阅读完成。
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 attackedvm 也存在安全问题,对于执行外部的代码,可能引发安全问题。
所以有个开源库专门解决了这个问题,https://github.com/patriksimek/vm2,声明已经过滤了所有已知攻击。