如何在沙盒中使用Rhino for Java运行Javascript?

时间:2008-09-18 16:01:36

标签: java javascript sandbox rhino

我们的部分Java应用程序需要运行由非开发人员编写的javascript。这些非开发人员使用javascript进行数据格式化。 (主要是简单的逻辑和字符串连接)。

我的问题是如何设置这些脚本的执行以确保脚本错误不会对应用程序的其余部分产生重大负面影响。

  • 需要防范无限循环
  • 防止产生新线程。
  • 限制对服务和环境的访问
    • 文件系统(示例:如果心怀不满的脚本编写者决定删除文件)
    • 数据库(同样删除数据库记录)

基本上我需要设置javascript范围,以便只包含他们需要的内容,而不是更多内容。

6 个答案:

答案 0 :(得分:20)

为防止无限循环,您可以在脚本运行时观察指令计数(这仅适用于已解释的脚本,而不适用于已编译的脚本)。

example in the Rhino JavaDocs来防止脚本运行超过十秒:

 protected void observeInstructionCount(Context cx, int instructionCount)
 {
     MyContext mcx = (MyContext)cx;
     long currentTime = System.currentTimeMillis();
     if (currentTime - mcx.startTime > 10*1000) {
         // More then 10 seconds from Context creation time:
         // it is time to stop the script.
         // Throw Error instance to ensure that script will never
         // get control back through catch or finally.
         throw new Error();
     }
 }

答案 1 :(得分:13)

要阻止Java类和方法访问,请查看...

http://codeutopia.net/blog/2009/01/02/sandboxing-rhino-in-java/

答案 2 :(得分:10)

为了防止无限循环,你需要将它放在一个单独的进程中,以便它可以被杀死。

为防止创建线程,您需要扩展SecurityManager(默认实现允许不受信任的代码访问非根线程组)。

Java安全性允许您阻止访问文件系统。

对于数据库限制,您可能可以使用标准SQL用户安全性,但这非常弱。否则,您需要提供一个强制执行限制的API。

编辑:我应该指出,JDK6提供的Rhino版本已经完成了安全工作,但不包括编译器。

答案 3 :(得分:1)

我刚刚浏览了这个博客文章,似乎对沙盒或多或少的任何东西都有用(不仅仅是Rhino):

http://calumleslie.blogspot.com/2008/06/simple-jvm-sandboxing.html

答案 4 :(得分:0)

如果您只是在寻找纯JavaScript函数,这里是一个基于JDK嵌入式Rhino库的解决方案,无需导入任何第三方库:

  1. 通过ScriptEngineManager#getEngineFactories
  2. 找出JavaScript脚本引擎工厂类名
  3. 在新的类加载器中加载脚本引擎工厂类,其中将忽略JavaMembers或其他相关类。
  4. 在已加载的脚本引擎工厂上调用#getScriptEngine,在返回的脚本引擎上调用eval脚本。
  5. 如果给定的脚本包含Java脚本,则类加载器将尝试加载JavaMembers或其他类并触发类未找到的异常。这样,恶意脚本将被忽略而不执行。

    请阅读ConfigJSParser.java和ConfigJSClassLoader.java文件以获取更多详细信息:

    https://github.com/webuzz/simpleconfig/tree/master/src/im/webuzz/config

答案 5 :(得分:-9)

Javascript是单线程的,无法访问文件系统,因此我认为您不必担心这些问题。我不确定是否有办法设置超时以防止无限循环,但你总是可以生成一个执行脚本的(Java)线程,然后在这么多时间后终止该线程。