在我的java应用程序中,我需要运行一些由用户上传的不受信任的代码。这可以通过与此类似的方式完成:
Java security: Sandboxing plugins loaded via URLClassLoader
但是,我们假设我有很多用户(每个都有一个线程),并且许多用户同时上传不受信任的代码。在运行代码之前使用System.setSecurityManager一次以锁定权限,然后再次使用后不再工作,因为多个线程可能同时调用此方法(例如,线程2只是启动方法并将安全管理器设置为沙箱版本,就像线程1将安全管理器设置为all allow all security manager一样,我们遇到了问题。
为了使这更棘手,有几个不同的对象,让我们只是称它们为User对象,所以如果我创建一个synchronized块:
synchonize(this){
// set security manager lockdown permissions
// run untrusted code
// set security manager all permissions
}
这几乎与使用对象同步的事实不同(许多线程不能在此方法中,对于此对象特定的同时)。
我理想情况下需要做的是,对于此类型的所有对象(静态?),请同步此块。因此,锁定所有用户使用此块直到完成。没关系,这些用户可以等。
因此,我可以想象这有效,但我不知道它是否完全符合我的预期。
synchronized(User.class){
}
我的问题是,所有这些听起来都是正确的,这是一种明智的做法吗?我使用超时等(以避免可能不受信任的代码挂起)。
我会对此进行测试,但实际上并不是很容易测试,而且看起来相当复杂(通常,当我发现我做的事情过于复杂时,这是因为它不是我应该做的事情)。所以在我开始讨论这个问题之前,上述情况是否正确,或者我错过了一些明显的东西?
修改:更多信息:
@edharned。更多关于这里发生的事情可能会有所帮助。服务器有一组JUnit测试,用户上传一些工作,服务器执行JUnit测试,但希望安全地执行。 JUnit测试不是在新进程中调用的,而是从主(并且只有)JVM中运行。这样就可以使用JUnitCore,并且调用方法可以计算出有多少测试,以及使用Result对象(http://junit.sourceforge.net/javadoc/org/junit/runner/Result.html)和运行监听器失败的次数/次数。如果使用junit.textui.TestRunner从新进程运行这些测试,那么我相信它只显示哪些测试失败(而不是哪个测试失败)。
也许解决方案是在它自己的JVM中运行每个JVM,它可以使用从JUnit测试类本身内部设置的安全管理器设置某些特权。但是,现在出现了一个新问题,即检索测试结果(通过,失败并有原因)。