📅  最后修改于: 2023-12-03 15:03:14.709000             🧑  作者: Mango
Node.js VM (Virtual Machine) 是 Node.js 自带的一个可执行代码执行环境,可以在 Node.js 中创建隔离的 JavaScript 执行环境,使得代码在一个严格的沙盒中运行,避免了一些代码安全上的问题。以下是 Node.js VM 的完整参考。
const { VM } = require('vm');
const vm = new VM();
vm.run(`
const message = 'Hello, world!';
console.log(message);
`);
以上代码会在 VM 中创建一个隔离的沙盒环境,并在沙盒中执行 JavaScript 代码,输出 Hello, world!
。
const { createContext } = require('vm');
const context = createContext({ message: 'Hello, world!' });
const script = new vm.Script(`
console.log(message);
`);
script.runInContext(context);
以上代码通过 createContext()
方法创建了一个上下文环境,定义了变量 message
的值为 Hello, world!
。然后通过创建一个 vm.Script
对象,把 JavaScript 代码传入其中,并调用 runInContext()
方法运行该脚本,输出 Hello, world!
。
const script = new vm.Script(`
console.log(message);
`);
script.runInNewContext({ message: 'Hello, world!' });
以上代码通过创建一个 vm.Script
对象,把 JavaScript 代码传入其中,并调用 runInNewContext()
方法运行该脚本,输出 Hello, world!
。在 runInNewContext()
方法中,我们通过传入一个对象,来创建新的上下文环境。
const script = new vm.Script(`
console.log(message);
`);
script.runInThisContext();
以上代码通过创建一个 vm.Script
对象,把 JavaScript 代码传入其中,并调用 runInThisContext()
方法运行该脚本,输出 ReferenceError: message is not defined
错误信息。这是因为 runInThisContext()
方法会在当前的上下文环境中运行代码,但当前的上下文环境中没有定义变量 message
。
const script = vm.createScript(`
const message = 'Hello, world!';
console.log(message);
`);
script.runInThisContext();
以上代码通过 vm.createScript()
方法编译 JavaScript 代码,返回一个 vm.Script
对象,然后调用 runInThisContext()
方法,在当前上下文环境中运行该脚本,输出 Hello, world!
。
可以使用 vm.createContext()
或 vm.runInContext()
创建一个沙盒环境,在该环境中执行 JavaScript 代码。以下是一个例子:
const sandbox = { message: 'Hello, world!' };
vm.createContext(sandbox);
vm.runInContext(`
console.log(message);
`, sandbox);
以上代码创建了一个沙盒环境,定义了变量 message
的值为 Hello, world!
,然后调用 vm.runInContext()
方法,在沙盒环境中执行 JavaScript 代码,输出 Hello, world!
。
可以使用 vm.createContext()
方法创建一个上下文环境,并通过 vm.setContext()
方法设置 VM 的全局上下文环境。以下是一个例子:
const context = vm.createContext({ message: 'Hello, world!' });
vm.setContext(context);
vm.runInThisContext(`
console.log(message);
`);
以上代码创建了一个上下文环境,定义了变量 message
的值为 Hello, world!
,然后通过 vm.setContext()
方法设置 VM 的全局上下文环境。最后调用 vm.runInThisContext()
方法,在当前上下文环境中执行 JavaScript 代码,输出 Hello, world!
。
可以使用 vm.createContext()
方法创建一个上下文环境,并在该环境中使用 require()
方法加载模块。以下是一个例子:
const fs = require('fs');
const vm = require('vm');
const path = require('path');
const context = vm.createContext({ require });
vm.runInContext(fs.readFileSync(path.join(__dirname, 'script.js')), context);
以上代码创建了一个上下文环境,并在该环境中使用 require()
方法加载 script.js
文件。
VM 中的模块加载在默认情况下是不安全的,因为可以加载系统级模块或其他从网络上加载的模块,如果这些模块是不受信任的,就会导致代码安全问题。可以通过配置 VM
,加强模块加载的安全性。以下是一个例子:
const { VM } = require('vm');
const vm = new VM({
require: {
external: true,
builtin: ['path', 'fs'],
root: './',
modules: {
'upper-case': {
path: './node_modules/upper-case/index.js',
module: require('upper-case')
}
}
}
});
const result = vm.run(`
const path = require('path');
const upperCase = require('upper-case');
const filepath = path.join(__dirname, 'test.txt');
const content = upperCase('Hello, world!');
require('fs').writeFileSync(filepath, content, 'utf8');
content;
`);
以上代码中,我们通过创建一个 VM
对象时,传入一个配置对象来加强模块加载的安全性。在配置对象中,我们可以设置 external: true
以允许加载来自 VM 外部的模块,也可以设置 builtin: ['path', 'fs']
以允许加载系统级模块以及一些特别的内置模块。我们还可以设置 root: './'
来指定模块的根目录,以及 modules
对象来提供自定义的模块。在以上代码中,我们提供了一个名为 upper-case
的自定义模块,该模块可以将字符串转为大写。
最后我们调用 vm.run()
方法,在沙盒环境中执行 JavaScript 代码,并返回大写的字符串。需要注意的是,代码中使用了 require()
方法来加载模块,并在 JavaScript 代码中编写了文件的写入操作,这个例子仅用于演示 VM
中的模块加载应该如何使用,实际操作中应考虑更多的安全性问题。