为什么我不能运行数据库中的JS?

时间:2015-04-23 15:31:18

标签: java javascript mongodb nashorn

我需要在mongoDB中运行以字符串格式保存的JS命令。为什么不以大写形式运行数据?

爪哇

public String read(String chave, String valor){
        String processador = atributoDAO.getProcessador(chave);
        if(processador != null){
            ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
            try {
                engine.eval(processador);
                Invocable invocable = (Invocable)engine;
                valor = (String)invocable.invokeFunction("process", valor);
            } catch (ScriptException e) {
                Log.error(AtributoReader.class, "erro no engine js", e);
            } catch (NoSuchMethodException e) {
                Log.error(AtributoReader.class, "erro no engine js", e);
            }
            return valor;
        }
        return valor;
    }

数据库

{
    "_id" : ObjectId("55390277e230ebff4fe25755"),
    "atributo" : "peca_nome",
    "processador" : "function(val) { return val.toUpperCase(); }"
}

2 个答案:

答案 0 :(得分:2)

执行engine.eval("function(val) { return val.toUpperCase(); }")时,您将在脚本引擎的范围内创建匿名函数。遗憾的是,以后无法调用它,因为函数未分配给变量。

您的呼叫invocable.invokeFunction("process", valor);尝试呼叫function process( val ),但脚本引擎的上下文中不存在具有该名称的功能。所以它会抛出一个NoSuchMethodException

有两种可能的解决方案。

重写数据库中的代码片段以将函数分配给变量,以便稍后调用它:

 {
    "_id" : ObjectId("55390277e230ebff4fe25755"),
    "atributo" : "peca_nome",
    "processador" : "process = function(val) { return val.toUpperCase(); };"
}

或者,在编译脚本之前,使用Java将变量添加到Javascript源代码中:

engine.eval("process = " + processador);

顺便说一句:在数据库中存储可执行代码通常是安全方面的一个非常危险的想法。如果有任何方法可以将用户提供的数据放入这些代码段中,则可以将应用程序打开到危险的代码执行漏洞。默认情况下,nashorn脚本引擎根本没有沙箱,非常强大。它可以执行JavaVM可以执行的任何操作,包括调用任何方法或从项目和java标准库构造任何对象。你在这里做什么看起来好像你要装满枪支。 如果你知道你在做什么,如果你遵循所有安全预防措施,它可能是安全的,但看起来你正准备开枪你自己(或其他人)。

答案 1 :(得分:0)

您可以评估匿名函数并将结果存储为对象。生成的对象是ScriptObjectMirror(https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/ScriptObjectMirror.html)类型,它有一个调用(https://docs.oracle.com/javase/8/docs/jdk/api/nashorn/jdk/nashorn/api/scripting/ScriptObjectMirror.html#call-java.lang.Object-java.lang.Object...-)函数的方法。

代码就像

Object thiz = engine.eval("this"); // get you global object
ScriptObjectMirror func = engine.eval("function() { print('hello'); }");
func.call(thiz); // pass global object as "this" for the function