Java安全机制

Java 安全机制是针对程序在操作本地资源时的权限限制,避免在执行有害代码时 (例如网络上下载的 jar 包)导致不可预估的损失。

这里简单介绍下使用方法。

配置安全策略

  1. 创建以 .policy 结尾的文件

  2. 配置授权规则,可以参考 Java 默认的策略文件 ${java.home}/jre/lib/security/java.policy

以下面配置文件的语法为例

grant codebase "file:${user.dir}/-" {
    permission java.io.FilePermission "${user.home}/*", "write";
};

其中定义了一条对 ${user.dir}/permission/ 路径下所有文件的权限,规定对 ${user.home} 路径下一层级的文件拥有写入权限。

codebase "url" 为可选项,表示权限规则的授予目标,不设置则对所有文件生效。也可使用 其他目标语法,或者自定义语法。

permission 表示一条权限规则,后面需跟随 继承 Permission 类的全路径类名、构造方法参数,以 ; 结尾,可设置多条规则。

  1. 设置策略文件
  • 追加策略文件 -Djava.security.policy=my.policy

  • 替换策略文件 -Djava.security.policy==my.policy

开启安全机制

一般开启安全机制的方式有两种,设置 JVM 参数,或者通过代码配置。

配置 JVM Options

-Djava.security.manager 
-Djava.security.policy=my.policy

代码设置

static {
    String dir = System.getProperty("user.dir");
    System.setProperty("java.security.policy", dir + "/my.policy");
    if (System.getSecurityManager() == null) {
        System.setSecurityManager(new SecurityManager());
    }
}

注意在使用代码时会与 JVM Options 方式冲突,抛出 java.security.AccessControlException: access denied 异常信息,需要配置权限规则解决,可以选择追加在 Java 策略文件里。

grant {
	permission java.lang.RuntimePermission "setSecurityManager";
	permission java.util.PropertyPermission "java.security.policy", "write";
	permission java.util.PropertyPermission "os.name", "read";
	permission java.util.PropertyPermission "user.home", "read";
	permission java.util.PropertyPermission "user.dir", "read";
};

跳过权限检查

对于开启了安全策略后又不想定义权限规则时,则可以使用 AccessController 类的 doPrivileged 方法,跳过 checkPermission 步骤,直接调用方法体。

AccessController.doPrivileged(new PrivilegedAction<Object>() {
    @Override
    public Object run() {
        ...
        return null;
    }
});

那么你可能会想,这样在其他依赖中也调用此方法不是绕过了安全机制。其实并不会,Java 在打包时会对实现了 PrivilegedAction 接口的元类信息进行清除,强制调用则会抛出 java.lang.NoClassDefFoundError

第三方工具

如果觉得默认的策略规则配置太繁琐了,那么可以使用 pro-grade 这个第三方依赖,他通过自定义语法简化了规则的配置,具体步骤可以参考 官网

<dependency>
    <groupId>net.sourceforge.pro-grade</groupId>
    <artifactId>pro-grade</artifactId>
    <version>1.1.3</version>
    <scope>compile</scope>
</dependency>