Java 什么时候应该使用AccessController.doPrivileged()?

Java 什么时候应该使用AccessController.doPrivileged()?,java,security,Java,Security,如果我理解正确,这意味着不受信任的代码应该能够通过具有权限的中间方法调用需要权限的方法(例如System.getProperty()) 这就提出了一个问题:什么时候应该使用AccessController.doPrivileged()?什么时候应该允许不受信任的代码通过中间方法调用特权代码?什么时候失败 按照您的推理,请解释为什么总是允许创建类加载器: 。通过具有权限的中间方法执行。否,最终有效权限是域堆栈中所有权限的交集。因此,假设一个操作需要一个权限B来执行,并假设某个中间库有两个权限B和a

如果我理解正确,这意味着不受信任的代码应该能够通过具有权限的中间方法调用需要权限的方法(例如
System.getProperty()

这就提出了一个问题:什么时候应该使用
AccessController.doPrivileged()
?什么时候应该允许不受信任的代码通过中间方法调用特权代码?什么时候失败

按照您的推理,请解释为什么总是允许创建类加载器:

  • 。通过具有权限的中间方法执行。否,最终有效权限是域堆栈中所有权限的交集。因此,假设一个操作需要一个权限B来执行,并假设某个中间库有两个权限B和a。现在,当一些只有权限a的不受信任代码通过库调用时,有效权限集是
    (a intersect(a+B))=a
    。因此,不受信任的代码无法利用中间库获得额外权限

  • 什么时候应该使用doPriveled?->Java中有很多操作需要调用方域具有某些权限才能成功执行这些操作。System.getProperty就是这些操作之一。所有与文件相关的操作也需要特殊权限。使用AccessController.doPrivileged调用这些操作时,将使用保护域的所有权限(权限)执行该操作。因此,如果您的代码只有足够的权限,那么它就可以执行这些操作

  • 同意,但我想添加一个具体示例,其中我需要使用特权块

    假设您构建了一个为可插拔模块提供大量服务的应用程序。因此,您的应用程序及其服务是可信的代码。但是,可插拔模块不一定受信任,而是加载在它们自己的类加载器中(并且有它们自己的保护域)


    当可插拔模块调用服务时,您正在实施自定义安全检查(“可插拔模块X是否具有使用此服务的权限”)。但是服务本身可能需要一些核心Java权限(读取系统属性、写入文件等)。需要这些权限的代码被包装在一个
    doPrivileged()
    中,这样就可以有效地忽略来自不受信任的可插拔模块的权限不足-只应用受信任服务模块的权限。

    查看这些链接并向下滚动以使用doPrivileged API

    Java 6:

    Java 7:

    当最近的调用方调用AccessController checkPermission方法时,决定是否允许或拒绝请求的访问的基本算法如下:


    如果调用链中任何调用方的代码不具有请求的权限,则会抛出AccessControlException,除非以下情况为真-其代码被授予所述权限的调用方已标记为“特权”(见下文),并且该调用方随后(直接或间接)调用了所有方它们都具有上述权限

    本质上,AccessController.doPrivileged()相当于一个设置的用户id文件。它的意思是“我在此请求以我的权限执行此方法,即使我被一个没有权限的方法调用。”

    @Suraj,“当您使用AccessController.doPrivileged调用这些操作时,该操作将以您的保护域的所有权限(权限)执行”。请举例说明使用和不使用doPrivileged()时的权限是什么?@Gilli..这将回答您的问题。。从技术上讲,每当试图访问资源时,执行线程在该点之前遍历的所有代码都必须具有访问该资源的权限,除非线程上的某些代码已被dopriveled块标记为“privileged”“我同意,如果A调用B,特权块只需采用B的权限。但是如果B然后调用C(即使是从特权块中),如果C的上下文没有所需的权限,它不会失败吗?它不是又开始从权限“堆栈”调用了吗?(我已经有一段时间没有在这方面做任何事情来测试它了——只是使用AccessController文档)。@Suraj,我已经重新讨论了这个问题,我认为你的第一点是错误的。我的理解如下:
    A
    不能访问磁盘上的文件,但是
    A
    可以构造
    Font
    ,即使它可以在引擎盖下访问磁盘上的文件。类
    Font
    将其文件访问权包装在
    doPrivileged()
    块中,本质上是说“即使调用方没有权限,也请相信我调用特权代码。我保证不会让他做任何他不应该做的事”。“你同意吗?”吉利我想你误解了。在第一点中,我说“最终有效权限是域堆栈中所有权限的交集”。要解决此问题,请使用AccessController.doPriveled。正如你所观察到的,这就是Font类所做的。@Ash,如果A有权调用X,但B没有,A调用B调用X。doPrivileged()是否意味着“B没有权限调用X,但我有,我为他担保。所以A现在可以调用X”?@Gili,我的理解是doPrivileged()块采用当前保护域的权限,不包括堆栈中的任何内容。它不一定会将权限转发给以后自己权限较低的调用(我在内存中工作并解释文档-请参阅我在Suraj回答中的评论)。引起我注意的引语是:
    将代码标记为“特权”启用一段受信任的代码以临时启用对可用资源以外的资源的访问