Java SecurityManager 多线程
Posted
技术标签:
【中文标题】Java SecurityManager 多线程【英文标题】:Java SecurityManager multiple threads 【发布时间】:2011-05-10 11:39:01 【问题描述】:我一直在尝试使用自定义 SecurityManager 来沙箱化一些外部加载的代码。我拥有的 SecurityManager 工作正常。我采取了与这里许多帖子建议的方法相同的方法:每当执行潜在危险代码时设置自定义管理器,然后恢复为标准管理器。这工作正常,做我想要的。但是,该应用程序是多线程的:2 个线程使用自定义管理器,1 个使用默认管理器。这会导致受信任代码可能无法正常运行,因为另一个线程只是设置了自定义安全管理器。有没有办法解决这个问题?或者,有更好的方法吗?我看到一些帖子谈论对同一个安全管理器使用不同的策略,但我找不到一个很好的例子。非常感谢任何帮助。
【问题讨论】:
这是哪条路?是外部加载的代码需要(并且正在被授予)更高的权限吗? 外部加载的代码应该有最小权限,主代码/主线程(加载外部代码)应该有所有权限。 我们也遇到过类似的问题,据我所知,安全管理器是唯一的,并且为整个虚拟机共享,您不能同时拥有不同的安全管理器。您将不得不在同步块或类似的东西中运行您的线程代码的某些部分(丑陋) 好的 - 我的建议将与下面彼得的建议一致。 我采取了与这里许多帖子建议的方法相同的方法:在执行潜在危险代码时设置自定义管理器,然后恢复为标准管理器。 呃,谁有建议这样做?您始终可以确定调用线程和调用 AccessControlContext ......这就是不应该这样做的方式(简而言之,设置/取消设置 SM 不是要走的路) 【参考方案1】:您的 SecurityManager 可以检查正在运行的线程。一个简单的本地线程可以做到这一点,但是,您可能需要一个 InheritableThreadLocal 以便创建的任何其他线程“继承”线程安全级别。
【讨论】:
这似乎“棘手”要正确。假设一个给定的线程可能会随着时间的推移在不同的上下文中运行,因此您需要在启动新线程时传播当前上下文(并且可能不会通过对旧线程的任何更改将其改回)。此外,您需要担心线程池或其他可以共享线程的地方。 感谢您的回答。我现在已经实现了类似的东西:主线程“注册”那些被认为不受信任的线程(使用它们的 id),SecurityManger 中的 checkPermission 方法检查调用线程的 id。但是,如果不受信任的代码创建子线程,这可能不起作用。目前,这是不允许的。但如果需要,那么上述方法可能会失败。 @coderino - 我不知道你维护线程 ID 多长时间,但要注意不能保证线程 ID 在 jvm 的生命周期内是唯一的(如 javadoc @ 中所述987654321@). 使用InheritableThreadLocal
解决了子线程和线程名不唯一的问题。您可以将所有线程称为“主线程”,并且可以使用 Thread.setName() 进行更改。
@Peter Lawrey - 只要值是不可变对象,ITL 将适用于直接生成的线程(因此更改父线程的值不会更改子线程的值)。它不能解决共享线程问题(例如线程池)。最终,我仍然认为最好按照设计使用 java 安全架构,“意外”特权泄漏的风险要小得多。 (另外,唯一性问题是线程 ID,而不是名称)。【参考方案2】:
您为整个应用程序使用一个安全管理器。 Java 安全框架旨在处理这种情况。让事情工作的方式是使用策略文件的代码库功能,它使您能够为不同的代码库分配不同的权限。您可以分配您的“主要”代码库“所有权限”,它将正常运行。您可以将任何导入的代码分配给受限制的代码库。
here 都有大量文档记录,可能与此问题最相关的部分是 policy file information。
【讨论】:
我会试一试的。有没有关于这方面的好文档,包括示例? 添加了相关 sun/oracle 文档的链接。 太好了,谢谢。我将浏览这些参考资料,看看我可以使用什么。【参考方案3】:测试当前线程或删除安全限制不是一个好主意。 举个例子,假设不受信任的代码有一个喜欢睡觉的终结器?
【讨论】:
以上是关于Java SecurityManager 多线程的主要内容,如果未能解决你的问题,请参考以下文章