Java沙盒。使用SecurityManager重定向I/O访问

Java沙盒。使用SecurityManager重定向I/O访问,java,sandbox,securitymanager,Java,Sandbox,Securitymanager,目前,我正在尝试编写沙箱来运行不受信任的Java代码。其思想是将Java应用程序与访问文件系统或网络套接字隔离开来。我目前的解决方案是重写SecurityManager,它禁止任何对IO或网络的访问 现在我不想禁止,而是想将调用重定向到文件系统,即如果应用程序想写入“/home/user/application.txt”,则文件路径应该替换为类似“/temp/trusted_folder/application.txt”。所以基本上我想允许应用程序只访问某个特定文件夹中的文件系统,并将所有其他调

目前,我正在尝试编写沙箱来运行不受信任的Java代码。其思想是将Java应用程序与访问文件系统或网络套接字隔离开来。我目前的解决方案是重写SecurityManager,它禁止任何对IO或网络的访问

现在我不想禁止,而是想将调用重定向到文件系统,即如果应用程序想写入“/home/user/application.txt”,则文件路径应该替换为类似“/temp/trusted_folder/application.txt”。所以基本上我想允许应用程序只访问某个特定文件夹中的文件系统,并将所有其他调用重定向到此文件夹

下面是类FileOutputStream中的方法,其中询问SM是否有写入给定路径的权限

 public FileOutputStream(File file, boolean append)
    throws FileNotFoundException
{
    String name = (file != null ? file.getPath() : null);
    SecurityManager security = System.getSecurityManager();
    if (security != null) {
        security.checkWrite(name);
    }
    if (name == null) {
        throw new NullPointerException();
    }
    fd = new FileDescriptor();
    fd.incrementAndGetUseCount();
    this.append = append;
    if (append) {
        openAppend(name);
    } else {
        open(name);
    }
}
显然,SM没有对FileOutputStream的访问权限,并且不能更改方法中的内部变量(如名称或文件),也不能以某种方式影响执行顺序,除非抛出SecurityException。我理解,访问内部字段违反了面向对象的原则,我理解,局部变量是可见的,并且只存在于声明它们的方法内部

所以我的问题是:有没有办法让安全管理器替换对文件系统的调用?如果没有,我是否可以使用其他方法来实现这一点


我希望我说得够清楚了

安全管理器无法做到这一点,它只能说是或否

我可以想出两个选择:

  • 在操作系统级别对文件系统执行一些操作。有这样的事情。这对于应用程序来说是透明的,但需要在Java之外工作

  • 向为他们打开FileOutputStream的应用程序提供API。API层可以决定文件的来源,并且有权(用安全管理器的术语)从任何地方打开文件。当然,这要求沙盒应用程序使用您的API,而不是直接使用
    java.io.File
    。但它也更加灵活,在某些情况下,应用程序可能需要了解沙盒并使用沙盒API,就像在JavaWebStart上一样


  • 我认为这是办不到的。 安全管理器设计用于拒绝访问特定操作,而不是重定向IO或执行其他类似操作

    即使通过一些严重的反射黑客技术,它也可能无法在不同的jvm供应商之间移植,甚至在运行同一jvm的不同操作系统之间移植。(这是因为您需要操作特定于操作系统的类)


    您想做的事情应该在较低的级别上尝试,请参阅chroot for linux和其他较重的虚拟化技术。

    我认为您想做的事情已经由Wealthfront的工程师实现了。

    以下是他们的博客文章:

    既然Java是开源的,您可以将源代码下载到
    FileOutputStream
    ,修改其源代码以强制执行您想要的任何约束,重新编译它,将它添加到jar,并将该jar预先添加到JVM的引导加载程序类路径:

    java -Xbootclasspath/p:myModifiedJavaClasses.jar sandbox.Main -run untrusted.Main
    
    JVM现在将使用
    java.io.FileOutputStream的实现,而不是通常的实现。清洗并重复所有需要特殊沙盒重定向逻辑的JSE类


    它不是最具可移植性或最易于部署的解决方案,因为它需要“在虚拟机之外”修改启动参数,但在某些情况下,此解决方案可能是可接受和有效的。

    本文没有这样说。他们描述的是一个安全管理器,它审计并可能禁止意外的I/O操作。不允许,不修改。谢谢你的回答。第一个选项我不能接受,因为我不想把自己限制在一个操作系统上,但是第二个选项看起来很不错。我搜索了一些API替换,发现JMockit工具可以模拟类和存根。所以基本上我会研究它,我认为这就是我现在需要的。我自己也在使用它,但是在Java9中,Xbootclasspath和Xbootclasspath/p被删除了。现在,应该使用补丁模块。还在读这些变化来理解它,哈哈