eval的替代品

我的程序处理许多不同types的文件,从中提取信息。 它有一个非常通用的结构来适应我们使用的数百种不同types/格式的文档。

处理器代码:

Processor.prototype.process = function(){ var self = this; var fields = self.processor_config; var p = {}; for(key in fields){ if(fields.hasOwnProperty(key)){ p[key]=self._processKey(fields[key]); if(typeof(p[key])=='undefined' || p[key]===''){ self.emit('warning', { type: 'Problem parsing Key', msg: 'Key : '+key, doc: self.docName }); } } } self.emit('extracted',p); }; 

processKey()函数然后根据“types”字段sorting出要执行的操作:

 Productor.prototype._processKey = function(cnf) { var self = this; var value; if(cnf.type=="css"){ value = self._processCSSKey(cnf); }else if(cnf.type=="regexp"){ value = self._processRegexpKey(cnf); }else if(cnf.type=="custom"){ value = self._processCustomKey(cnf); } return value; }; 

有关从每种types的文档中提取什么的信息来自于一个mongodb集合:

与2种types的字段的虚构configuration:

 doc_name: "FormK7", processor_config: { company:{ type:"css" selector:"p", ord:3, attr:{type:"text",parser:""} }, litigation:{ type:"custom" func:"(function(){var a =['123'];return a})()" }, } 

上面的例子是相当无用的,但真正的事情有更复杂的function(虽然不多)。

我的定制处理器如下所示:

 Productor.prototype._processCustomKey = function(cnf) { var value = eval(cnf.func); return value; }; 

我的问题是,我还没有find一种方法来处理自定义键没有使用eval。 然而,简单地提到“eval”让我想起了一个愤怒的道格拉斯·克罗克福德(Douglas Crockford)的照片,把我驱逐到了所有永恒的黑暗中。

附加信息 :

  • 在现实生活中,存储在mongo中的函数被缩小。

  • 通用处理器是需要的,因为每种文档types都有一个处理器是非常浪费的(格式一直在改变,其中有数百个处理器,有些处理器只能使用一次)。 所以这些function需要以某种方式进行logging。 他们太不同了,难以编码…

  • 没有用户input,应用程序无法从networking访问。 恶意用户在能够使用mongo注入代码之前就能够访问服务器,所以安全性非常低。

所以问题如下:

在这种情况下,eval是否真的很邪恶,还是一个有效的用例呢? 有没有更好的方法来处理这个问题?

您可以创build一个从mongo导出到临时文件的模块,然后使用require导入该文件。 这样你就不会被评估,就像Bergi提到的那样,它可以防止eval的范围问题。

另外,一旦你导出它,并在需要之前,你可以使用像Esprima这样的东西来创build代码的AST并分析它,看看它是否符合你可能有的标准。 (也许,你可以禁止在导入的代码中使用this作为安全措施 – 这是ADSafe规则的一部分)