0

上一个问题中,我想出了如何从 repl 上下文中消除不需要的全局变量。但是,我发现 repl 可以自动访问所有内部节点模块,而无需使用require. 我不知道如何禁用它。我什至尝试覆盖 repl 本身中的模块变量,但它不起作用。

> fs = "测试";
> fs

它仍然显示fs原始值。这是非常不幸的,因为我试图公开一个公共 repl,但它使他们能够访问整个服务器。

有任何想法吗?

4

1 回答 1

2

正如您所说,REPL 可以访问核心模块

(但是,检查后,我可以用节点 0.10.20 覆盖它们,所以应该有一个解决方案)

> fs
> { Stats: [Function], …
> fs = 'hello';
> fs
'hello'

更好的方法是repl._builtinLibs在创建 repl 实例之前覆盖。

var repl = require('repl');
repl._builtinLibs = [];
repl.start('> ');

此外,如果您不想公开诸如.saveor之类的命令,将 repl 命令列入白名单也相当简单.load

var allowedReplCmds = ['.break', '.clear', '.help'];

var newRepl = repl.start('> ');
for (var key in newRepl.commands)
    if (!allowedReplCmds.contains(key))
        delete replInstance.commands[key];

注意:数组通常没有contains方法,所以我添加了一个。

Array.prototype.contains = function(v) {
    for(var i = 0; i < this.length; i++) {
        if(this[i] === v) return true;
    }
    return false;
};

如果要从 repl 实例的全局范围中删除变量,请参阅此问题


请注意,将 REPL 公开给公众是非常不安全的。

您可以轻松地使整个服务器崩溃

> setTimeout(function () { throw 'bye bye!'; }, 0);

异步回调中发生的错误不会被 REPL 捕获并关闭 node.js 实例。

您可以阻止服务器

> while(true) {};

你最好的办法是在一个单独的进程中使用 child_process、readline 和 vm 编写你自己的 REPL。这是一个起点:

大师:

// master.js
var fork = require('child_process').fork;

// functions exposed to the repl
var replApi = {
  hello: function () {
    return 'world!';
  },

  unknown: function () {
    return 'unknown';
  }
};

function forkRepl() {
  var repl = fork('./child_repl');

  repl.on('message', function (command) {
    var fun = replApi[command] || replApi.unknown;
     repl.send(fun());
  });

  // restart the repl if it dies
  repl.on('exit', forkRepl);
}

forkRepl();

以及 repl 的单独过程:

// child_repl.js
var readline = require('readline'),
    vm = require('vm');

var context = vm.createContext({
  hello: function () {
    process.send('hello');
  }
});

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.on('line', function (line) {
  vm.runInContext(line, context, 'repl.vm');
});

process.on('message', function (message) {
  console.log('master:', message);
});

rl.prompt();
于 2013-10-16T09:42:18.827 回答