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规则的一部分)