AccessController用法

我正在尝试了解java安全性的基础知识和AccessController.doPrivileged()用法我开始使用示例程序

import java.security.AccessController; import java.security.PrivilegedAction; public class AccessSystemProperty { public static void main(String[] args) { System.out.println(System.getSecurityManager()); AccessController.doPrivileged( new PrivilegedAction(){ public Boolean run(){ System.out.println(System.getProperty("java.home")); return Boolean.TRUE; } } ); } } 

如果我尝试使用默认安全管理运行上面的代码我得到AccessControlException我的stacktrace是

 C:\>java -Djava.security.manager AccessSystemProperty java.lang.SecurityManager@923e30 Exception in thread "main" java.security.AccessControlException: access denied ( java.util.PropertyPermission java.home read) at java.security.AccessControlContext.checkPermission(Unknown Source) at java.security.AccessController.checkPermission(Unknown Source) at java.lang.SecurityManager.checkPermission(Unknown Source) at java.lang.SecurityManager.checkPropertyAccess(Unknown Source) at java.lang.System.getProperty(Unknown Source) at AccessSystemProperty$1.run(AccessSystemProperty.java:9) at AccessSystemProperty$1.run(AccessSystemProperty.java:8) at java.security.AccessController.doPrivileged(Native Method) at AccessSystemProperty.main(AccessSystemProperty.java:6) 

请帮助我清楚地了解一下

1)当我们需要使用AccessController.doPrivileged()?.(如果存在SecurityManager,我们使用AccessController.doPrivileged为什么在上面的示例中失败)2)使用AccessController和PrivilegedAction获得的真正优势是什么? 3)我们是否需要上述示例的自定义策略文件才能工作? 谢谢,保罗

您可以使用AccessController.doPrivileged()来提供某些代码权限,这些权限在调用堆栈中较早的代码没有,但由于在策略中授予了该权限,特权代码具有哪些权限。

例如,假设ClassA调用ClassB上的方法,而ClassB需要读取java.home系统属性(从您的示例中借用),并假设您已根据示例指定SecurityManager存在。

还假设从名为“classb.jar”的jar加载ClassB(但为了使示例工作ClassA不从该jar加载),以下内容应该在安全策略文件中:

 grant codeBase "file:/home/somebody/classb.jar" { permission java.util.PropertyPermission "java.home", "read"; }; 

现在当ClassB运行并尝试执行一个System.getProperty()时,它不包含在“java.home”上的AccessController.doPrivileged()中。 安全管理器将检查堆栈,以查看堆栈中较高的每个类是否具有“java.home”的PropertyPermission(无论是直接还是暗示)。 如果没有,访问将失败。

但是,如果ClassB将System.getProperty()包装在AccessController.doPrivileged()中,则安全管理器只关心策略文件为ClassB提供该特权,因此允许访问。

这是一个显示这个的片段:

 public void doStuff() { try { /* * this will fail even if this class has permission via the policy file * IF any caller does not have permission */ System.out.println(System.getProperty("java.home")); } catch (Exception e1) { System.out.println(e1.getMessage()); } AccessController.doPrivileged(new PrivilegedAction() { public Boolean run() { try { /* * this will be allowed if this class has permission via the policy * file even if no caller has permission */ System.out.println(System.getProperty("java.home")); } catch (Exception e) { System.out.println(e.getMessage()); } return Boolean.TRUE; } }); 

因此,对于您的示例,您只需要指定一个策略文件,其中包含与上面引用的grant节类似的内容。