评估的替代方案

时间:2014-11-06 18:40:05

标签: 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)){
            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()函数然后根据"类型"来排序要做的事情。领域:

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;
};

从每种类型的文档中提取的内容的信息来自mongodb集合:

包含两种类型字段的虚构配置:

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'让我想起一个愤怒的道格拉斯·克罗克福德(Douglas Crockford)的照片,让我永远地被黑暗遗忘......

其他信息:

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

  • 需要通用处理器,因为每种文档类型只有一个处理器会非常浪费(格式一直在变化,其中有数百种,有些仅使用一次......)。所以这些功能需要以某种方式记录。而且他们太不同了,难以被硬编码......

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

所以问题如下:

在这种情况下,eval真的是邪恶的,还是一个有效的用例?有没有更好的方法/最佳实践来解决这个问题?

1 个答案:

答案 0 :(得分:1)

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

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