Javascript 评估的替代方案

Javascript 评估的替代方案,javascript,node.js,eval,Javascript,Node.js,Eval,我的程序处理许多不同类型的文档以从中提取信息。 它有一个非常通用的结构,适合我们使用的数百种不同类型/格式的文档 处理器代码: Processor.prototype.process = function(){ var self = this; var fields = self.processor_config; var p = {}; for(key in fields){ if(fields.hasOwnProperty(key)){

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

处理器代码:

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);
};
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})()"
    },
}
然后,processKey()函数根据“类型”字段排序要执行的操作:

关于从每种类型的文档中提取什么的信息来自mongodb集合:

具有两种字段类型的虚构配置:

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);
};
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})()"
    },
}
上面的例子是非常无用的,但真正的东西有更复杂的功能(虽然不是很多)

我的自定义处理器看起来像:

Productor.prototype._processCustomKey = function(cnf) {
    var value = eval(cnf.func);
    return value;
};
我的问题是,我还没有找到一种不使用eval处理自定义密钥的方法。然而,只要一提到“eval”,我就会想起一幅愤怒的道格拉斯·克罗克福德将我永远驱逐到黑暗中的画面

其他信息:

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);
};
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})()"
    },
}
  • 在现实生活中,存储在mongo中的函数被缩小了

  • 通用处理器是必需的,因为每个文档类型有一个处理器是非常浪费的(格式一直在变化,有数百个,有些只使用一次…)。所以这些函数需要以某种方式记录下来。它们太不一样了,不能硬编码

  • 没有用户输入,无法从web访问该应用程序。恶意用户在能够在mongo中注入代码之前可以访问服务器,因此安全问题非常低

因此,问题如下:


在这种情况下eval真的很邪恶吗,或者它是一个有效的用例吗?有更好的方法/最佳实践来处理这个问题吗?

您可以创建一个模块,从mongo导出到一个临时文件,然后使用
require
导入该文件。这样您就不会进行evaling,正如Bergi提到的那样,它将防止
eval
出现的范围问题


此外,一旦导出它,在需要它之前,您可以使用Esprima之类的工具创建代码的AST,并对其进行分析,以查看它是否符合您可能有的某些标准。(比如,也许你可以禁止在作为安全措施导入的代码中使用
this
,这是ADSafe的规则的一部分)

首先不清楚你应该在哪里使用
eval
。通常避免它的原因是运行任意用户数据,这是非常危险的。如果你正在构建和清理其中的内容,这并不完全疯狂,但你必须非常小心,这就是为什么它通常是最后的工具。我在“processCustomKey”函数中使用eval。我也同意这是最后的办法,但我想不出其他办法。输入经过消毒,配置与用户可以看到的任何内容都不接近。该特定组件被深埋在后端的后面;)如果您提供一个更复杂的函数示例,可能会更好。在这个例子中,你可以有一个值为
[1,2,3]
的属性,但当然这只是一个例子来证明你的观点。我猜你不能只在配置中存储一个简单的函数表达式,对吧?它可能是一个日期操纵,或者几乎是任何小的操作,关键是定制函数的功能有数百种可能的变化。