代码之家  ›  专栏  ›  技术社区  ›  BUKTOP

在Nashorn中禁用ECMAScript扩展

  •  1
  • BUKTOP  · 技术社区  · 6 年前

    我需要在我的应用程序中运行一个简单的脚本,用户应该能够输入/修改这个脚本本身。该脚本旨在检查/修改一些数据/字段集,例如可以表示为哈希表。逻辑很简单-检查一些值,并根据以前的检查修改其他值。逻辑很简单,但应该是灵活的,我有一个使用lua的“遗留”C程序。我首先找到了luaj,但后来我发现现代Java支持现成的ECMAScript,这就是我尝试使用Nashorn的原因。然后我发现Nashorn与jvm的集成太多,这可能会导致滥用。因此,我试图防止滥用禁用某些功能。首先,我发现了一些命令行参数,这些参数阻止了脚本中某些扩展和java类的可用性。我还发现,Nashorn公开了一些潜在危险的函数,如quit()、load()等。因此,我的代码如下所示:

    ScriptEngine engine=new NashornScriptEngineFactory().getScriptEngine(new String[]{"-nj", "-nse"}, null
            new ClassFilter()
            {
                @Override
                public boolean exposeToScripts(String s)
                {
                    return false;
                }
            });
    Bindings bd;
    bd=engine.getBindings(ScriptContext.ENGINE_SCOPE);
    bd.remove("loadWithNewGlobal");
    bd.remove("load");
    bd.remove("quit");
    // ... and so on
    

    据我所知,由于“bd”是引用,它删除了实际的绑定,并且不能从脚本内部调用这些函数。但后来我试图列出所有绑定,却发现没有!甚至在删除之前,我看到bd的大小为“0”,绑定映射为空:

    System.out.printf("Bindings no: %d\n", bd.size());    
    for(String key : bd.keySet())
    {
        System.out.printf("'%s'='%s'\n", key, bd.get(key).toString());
    }
    

    打印“0”,仅此而已。

    所以,我实际上有两个问题: 1) 为什么我看不到所有绑定?(虽然我可以删除它们,而且我发现如果不删除这些函数,就可以从脚本中调用这些函数,但在我删除它们之后,它们就不再可用了,每次调用都会引发一个异常) 那么我如何列出绑定的内容呢? 2) 还有什么我忘了的,应该在脚本中禁用的吗?(当然,除了无限循环等等,用户或多或少都是“受信任的”,但我还是想防止一些“危险”的行为)

    非常感谢。

    2 回复  |  直到 6 年前
        1
  •  3
  •   A. Sundararajan    6 年前

    第一部分:

    如果在全局范围内求值以下内容,则将获得所有属性,包括不可枚举的属性。

    Object.getOwnPropertyNames(this)
    

    另请参见: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames

    (在“BblKTOP”发表评论后更新)

    使用javax迭代密钥集时,只返回(JS)可枚举属性。剧本绑定。但也有对象的等价物。getOwnPropertyNames(此)。这可能是这样的:

    import javax.script.*;
    import jdk.nashorn.api.scripting.*;
    
    public class Main {
       public static void main(String[] args) throws Exception {
          ScriptEngineManager m = new ScriptEngineManager();
          ScriptEngine e = m.getEngineByName("nashorn");
          ScriptObjectMirror thiz = (ScriptObjectMirror)e.eval("this");
          // ScriptObjectMirror.getOwnKeys(boolean) returns all own property names. 
          // "true" to return all non-enumerable property names as well.
          // This is equivalent to JS call:
          //     Object.getOwnPropertyNames(this)
          for (String key : thiz.getOwnKeys(true)) {
              System.out.println(key);
          }
       }
    }
    

    第二部分:

    我想你似乎已经掩饰了。但您可能需要确保在启用security manager的情况下运行。设置安全管理器后,所有脚本“eval”-ed都被视为沙盒脚本,因此不允许进行安全敏感操作。

    沙箱的另一种选择:考虑一种可以转换为JavaScript的特定于域的语言。

        2
  •  0
  •   BUKTOP    6 年前

    发现Nashorn通过ScriptObjectMirror#getOwnKeys返回有效属性。以下代码打印有效绑定:

        bd=engine.getBindings(ScriptContext.ENGINE_SCOPE);
        for(String key : ((ScriptObjectMirror) bd).getOwnKeys(true))
        {
            if(key!=null)
            {
                System.out.printf("'%s'='%s'\n", key, bd.get(key));
            }
        }