我想将文本输入作为对象的子查询运行。
更好理解的例子:
//input: "all();"
collection.all(); //actual code ran
//input: "where({age: 10}).limit(10);"
collection.where({age: 10}).limit(10); //actual code ran
子查询可能包含的所有可能功能都是未知的,因此无法将其过滤掉。
最简单的解决方案是使用eval:
function run(subquery) {
return eval('collection.' + subquery);
}
然而,这允许代码注入,例如:run('all();alert("dough!");');
如何安全地执行任意代码作为子查询?(也欢迎Node.js具体答案);
答案 0 :(得分:0)
您可以使用VM module,它允许您在沙盒环境中执行JS。
有关示例,请参阅vm.runInNewContext示例。
根据您需要的变量,最安全的方法应该是将这些变量复制到新的上下文中,禁止脚本修改现有的上下文。
注意:这是Node.JS特有的,不适用于浏览器本身。
答案 1 :(得分:0)
由于@ adeneo的想法,我能够让它工作。我将输入解析为这样的数组:
//where({age: 10}).limit(10);
var track = [{fn: 'where', args: {age: 10}}, {fn: 'limit', args: 10}]
我可以使用括号表示法:
for (var key in stack) {
var val = stack[key];
result = result[val.fn].apply(this, val.args);
}
我用来解析初始执行的方法是:
function init() {
var stack = [];
function push(fn, args) {
stack.push({
fn: fn,
args: args
})
};
return {
foo: function () {
push('foo', arguments);
return db;
},
bar: function () {
push('bar', arguments);
return db;
},
stack: function () {
return stack;
}
};
}
var db = init();
db.foo(1).bar({a: 5}).foo(false).stack();
这样做的一个缺点是它需要你定义每个可能的方法(foo和bar)。