我对Java安全经理的精通不好,因此想确认我的理解:
我有一个随机停止的Java进程(即使挂钩运行),即使没有人杀死它的痕迹。结果,我决定安装安全管理器并覆盖checkExit(int status)
,以确保停止的原因不是打电话给System.exit()
。基本上我写了这篇文章:
System.setSecurityManager(new SecurityManager() {
@Override
public void checkExit(int status) {
Thread.dumpStack();
super.checkExit(status);
}
});
我期望我的程序会照常运行,唯一的变化是,如果调用了system.exit(),则会丢弃堆栈跟踪。我发现事实并非如此。它未能从此安全性例外开始:
java.security.AccessControlException: access denied ("java.util.PropertyPermission" "config" "read")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472) ~[na:1.8.0_74]
at java.security.AccessController.checkPermission(AccessController.java:884) ~[na:1.8.0_74]
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549) ~[na:1.8.0_74]
at java.lang.SecurityManager.checkPropertyAccess(SecurityManager.java:1294) ~[na:1.8.0_74]
at java.lang.System.getProperty(System.java:717) ~[na:1.8.0_74]
at Main.main(Main.java:161) ~[na:na]
看来,SecurityManager并未复制默认行为,并且在阅读后,它似乎应用了${JAVA_HOME}/jre/lib/security/java.policy
下的默认策略,这是非常限制的。
当没有安全管理器时,Java的真正默认行为是什么?是"允许一切"还是发生其他事情发生?
如果我想复制默认行为,除了上面的单个调整之外,我应该以安全管理器的身份安装?
在最后一点上,我可以看到System.setSecurityManager()
实际上期望java.lang.SecurityManager
的实例,这意味着我被迫使用该实现(依赖于策略文件)。在该类中覆盖方法以复制没有安全管理器的实际默认行为的最有效方法是什么?
编辑:根据下面的讨论,这似乎是这样做的
System.setSecurityManager(new SecurityManager() {
@Override
public void checkPermission(Permission perm) {
return; // no security manager behaviour
}
@Override
public void checkPermission(Permission perm, Object context) {
return; // no security manager behaviour
}
@Override
public void checkExit(int status) {
Thread.dumpStack();
super.checkExit(status);
}
});
你很困惑。
看来,SecurityManager并未复制默认行为,并且在阅读后,它似乎在$ {java_home}/jre/lib/security/java.policy.policy.policy中应用了默认策略。
SecurityManager
的默认行为是遵守Javadoc中所述的合同,, 默认文件允许的.policy
文件确实非常限制。安全管理器的缺勤中的默认行为是允许任何事情。
当没有安全管理器时,Java的真正默认行为是什么?是"允许一切"
是。
还是还有其他事情发生?
no。
如果我想复制默认行为,除了上面的单个调整之外,我应该以安全管理器的身份安装?
确切地做到这一点的安全经理。如果您希望它执行除了实施的替代之外,则必须为其所有其他方法提供空覆盖。