Java沙盒。使用SecurityManager重定向I/O访问
目前,我正在尝试编写沙箱来运行不受信任的Java代码。其思想是将Java应用程序与访问文件系统或网络套接字隔离开来。我目前的解决方案是重写SecurityManager,它禁止任何对IO或网络的访问 现在我不想禁止,而是想将调用重定向到文件系统,即如果应用程序想写入“/home/user/application.txt”,则文件路径应该替换为类似“/temp/trusted_folder/application.txt”。所以基本上我想允许应用程序只访问某个特定文件夹中的文件系统,并将所有其他调用重定向到此文件夹 下面是类FileOutputStream中的方法,其中询问SM是否有写入给定路径的权限Java沙盒。使用SecurityManager重定向I/O访问,java,sandbox,securitymanager,Java,Sandbox,Securitymanager,目前,我正在尝试编写沙箱来运行不受信任的Java代码。其思想是将Java应用程序与访问文件系统或网络套接字隔离开来。我目前的解决方案是重写SecurityManager,它禁止任何对IO或网络的访问 现在我不想禁止,而是想将调用重定向到文件系统,即如果应用程序想写入“/home/user/application.txt”,则文件路径应该替换为类似“/temp/trusted_folder/application.txt”。所以基本上我想允许应用程序只访问某个特定文件夹中的文件系统,并将所有其他调
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.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被删除了。现在,应该使用补丁模块。还在读这些变化来理解它,哈哈