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

时间:2020-03-06 14:22:07  来源:igfitidea点击:

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

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

  • 需要防范无限循环
  • 防止产生新线程。
  • 数据库(用同样的方法删除数据库记录)

基本上,我需要将javascript范围设置为仅包含其所需内容,而不再包含其他内容。

解决方案

Javascript是单线程的,无法访问文件系统,因此我认为我们不必为此担心。我不确定是否可以设置超时来防止无限循环,但是我们总是可以生成一个执行脚本的(Java)线程,然后在很长一段时间后杀死该线程。

为了防止无限循环,我们需要将其放在单独的进程中,以便将其杀死。

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

Java安全性确实允许我们阻止对文件系统的访问。

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

编辑:我应该指出,随JDK6一起提供的Rhino版本已经对其进行了安全性工作,但不包括编译器。

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

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

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

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