根据@Leigh和@ Miguel-F的有用建议,我尝试实施Security Manager
and Policy
。结果如下:
1.在运行时指定附加策略文件,而不是更改默认java.policy
文件。为此,我们使用 CFAdmin 接口将以下参数添加到 JVM 参数,或者将其附加到文件jvm.args
中的行jvm.config
:
-Djava.security.manager -Djava.security.policy="c:/policies/myRuntime.policy"
里面有一个不错的 GUI 实用程序,jre\bin\
它policytool.exe
允许您轻松有效地管理策略条目。
2.我们强制执行了安全管理器并提供了我们的自定义安全策略文件,其中包含:
grant codeBase "file:///D:/proj/secTestProj/main/-"{
permission java.io.FilePermission
"<<ALL FILES>>", "read, write, delete";
};
在这里,我们将FilePermission
所有文件设置为从列表中read, write, delete
排除execute
,因为我们不希望使用 java 运行时执行任何类型的文件。
注意:如果我们希望将策略应用于所有应用程序而不考虑来源,则可以将代码库设置为空字符串。
我真的希望deny
策略文件中的规则可以使事情变得更容易,类似于grant
我们正在使用的规则,但不幸的是没有。如果你需要制定一套复杂的安全策略,你可以使用Prograde库,它实现了带有拒绝规则的策略文件(stack ref.)。您当然可以替换<<ALL FILES>>
为单个文件并相应地设置权限,或者为了更好地控制使用<<ALL FILES>>
单个文件权限的组合。
参考:默认策略实现和策略文件语法、JDK 中的权限和控制应用程序
这种方法解决了我们的核心问题:通过指定文件允许的权限来拒绝使用 java 运行时执行文件。在其他方法中,我们可以Security Manager
直接在我们的应用程序中实现以从那里定义策略文件,而不是在我们的 JVM 参数中定义它。
//set the policy file as the system securuty policy
System.setProperty("java.security.policy", "file:/C:/java.policy");
// create a security manager
SecurityManager sm = new SecurityManager();
//alternatively, get the current securiy manager using System.getSecuriyManager()
//set the system security manager
System.setSecurityManager(sm);
为了能够设置它,我们需要策略文件中的这些权限:
permission java.lang.RuntimePermission "setSecurityManager";
permission java.lang.RuntimePermission "createSecurityManager";
permission java.lang.RuntimePermission "usePolicy";
在应用程序中使用安全管理器对象有其自身的优势,因为它公开了许多有用的方法,例如:CheckExec(String cmd)
检查调用线程是否允许创建子进程。
//perform the check
try{
sm.checkExec("notepad.exe");
}
catch(SecurityException e){
//do something...show warning.
}