policytool 是 Java 开发工具包(JDK)中的一个命令行工具,用于管理 Java 安全策略文件。Java 安全策略文件定义了 Java 运行时环境中的安全策略,包括允许或禁止特定操作、授予特定代码权限等。
Java 中的策略文件(通常称为 java.policy 文件)用于定义 Java 应用程序的安全策略,它详细说明了不同代码所拥有的不同资源的许可。安全策略由一个 Policy 对象来表达,为了让小程序(applet)或运行在 SecurityManager 下的应用程序能够执行受保护的行为(如读写文件等),必须获得相应操作的许可,而策略文件就是用来实现这些许可的。
Java 策略文件可以存储在无格式的 ASCII 文件、Policy 类的二进制文件或数据库中。下图是 Java 主目录下 jre/lib/security 子目录,该目录存在 java.policy 和 javaws.policy 两个策略文件:
java.policy 文件的内容如下:
// Standard extensions get all permissions by default // 标准扩展程序默认获得所有权限 grant codeBase "file:${{java.ext.dirs}}/*" { permission java.security.AllPermission; }; // default permissions granted to all domains // 授予所有域的默认权限 grant { // Allows any thread to stop itself using the java.lang.Thread.stop() // method that takes no argument. // 允许任何线程使用不带参数的 java.lang.Thread.stop() 方法停止自身运行。 // Note that this permission is granted by default only to remain // backwards compatible. // 请注意,默认情况下授予该权限只是为了保持向后兼容。 // It is strongly recommended that you either remove this permission // from this policy file or further restrict it to code sources // that you specify, because Thread.stop() is potentially unsafe. // See the API specification of java.lang.Thread.stop() for more // information. // 强烈建议您删除此权限或将其进一步限制在您指定的代码源中,因为 Thread.stop() 可能是不安全的。 // 有关详细信息,请参阅 java.lang.Thread.stop() 的 API 规范。 permission java.lang.RuntimePermission "stopThread"; // allows anyone to listen on dynamic ports // 允许任何人监听动态端口 permission java.net.SocketPermission "localhost:0", "listen"; // "standard" properies that can be read by anyone // 任何人都能读取的 "标准" 属性 permission java.util.PropertyPermission "java.version", "read"; permission java.util.PropertyPermission "java.vendor", "read"; permission java.util.PropertyPermission "java.vendor.url", "read"; permission java.util.PropertyPermission "java.class.version", "read"; permission java.util.PropertyPermission "os.name", "read"; permission java.util.PropertyPermission "os.version", "read"; permission java.util.PropertyPermission "os.arch", "read"; permission java.util.PropertyPermission "file.separator", "read"; permission java.util.PropertyPermission "path.separator", "read"; permission java.util.PropertyPermission "line.separator", "read"; permission java.util.PropertyPermission "java.specification.version", "read"; permission java.util.PropertyPermission "java.specification.vendor", "read"; permission java.util.PropertyPermission "java.specification.name", "read"; permission java.util.PropertyPermission "java.vm.specification.version", "read"; permission java.util.PropertyPermission "java.vm.specification.vendor", "read"; permission java.util.PropertyPermission "java.vm.specification.name", "read"; permission java.util.PropertyPermission "java.vm.version", "read"; permission java.util.PropertyPermission "java.vm.vendor", "read"; permission java.util.PropertyPermission "java.vm.name", "read"; };
以下是无格式的 ASCII 策略文件,一个策略文件实质上是一个记录列表,它可能含有一个“keystore”记录,以及零个或多个“grant”记录。其格式如下:
keystore "some_keystore_url","keystore_type"; grant (SignedBy "signer_names")(, CodeBase "URL") { Permission permission_class_name( "target_name")(, "action") (, SignedBy "signer_names"); Permission... };
策略文件的各部分具体含义如下:
keystore 记录:keystore 是一个私有密钥(private keys)数据库和相应的数字签名(例如 X.509 证书)。Policy 文件中可能只有一条 keystore 记录(也可能不含有该记录),它可以出现在文件中 grant 记录以外的任何地方。Policy 配置文件中指定的 keystore 用于寻找 grant 记录中指定的签名者的公共密钥(public keys),如果任何 grant 记录指定了签名者(signer_names),那么 keystore 记录必须出现在 policy 配置文件中。
some_keystore_url 是指 keystore 的 URL 位置。
keystore_type 是指 keystore 的类型。如果未指定类型,则假定由安全属性文件(java.security)中的“keystore.type”属性来确定。keystore 类型定义了 keystore 信息的存储和数据格式,以及用于保护 keystore 中的私有密钥和 keystore 完整性的算法,支持的缺省类型为“JKS”。
grant 记录:每一个 grant 记录含有一个 CodeSource(一个指定的代码)及其 permission(许可)。以保留字“grant”开头,表示一条新记录的开始,“Permission”是另一个保留字,在记录中用来标记一个新许可的开始。每一个 grant 记录授予一个指定的代码(CodeBase)一套许可(Permissions)。permission_class_name 必须是一个合格并存在的类名,例如 java.io.FilePermission,不能使用缩写。target_name 用来指定目标类的位置,可以直接指定类名(可以是绝对或相对路径)、目录名,也可以是一些通配符,如:
directory/* 目录下的所有文件
. 当前目录的所有文件
directory/- 目录下的所有文件,包括子目录
- 当前目录下的所有文件,包括子目录
<<ALL FILES>> 文件系统中的所有文件
action 用于指定目标类拥有的权限,例如对于 java.io.FilePermission,action 可以是:read、write、delete 和 execute;对于 java.net.SocketPermission,action 可以是:listen、accept、connect、read、write。
更多关于策略文件的信息,后续通过专题进行介绍。
在终端输入 policytool -help 命令,查看帮助信息:
C:\Users\Administrator> policytool -help 非法选项: -help 用法: policytool [选项] [-file <file>] 策略文件位置
在终端输入“policytool”命令,这将打开一个图形用户界面,用于创建、编辑和管理 Java 安全策略文件。如下图:
下面命令将创建一个名为 new.policy 的新安全策略文件,并打开安全策略工具界面,以便你可以添加和编辑策略条目。例如:
policytool -file new.policy
运行效果如下图:
点击“添加策略条目(A)”按钮,创建一个新条目,如下图:
上图,在“CodeBase(C)”输入框输入要授权的目录,然后点击“添加权限(D)”按钮添加权限,如下图:
上图选择“AllPermission”,授予所有权限。最后效果如下图:
最后生成的策略文件内容如下:
/* AUTOMATICALLY GENERATED ON Tue Jul 02 16:11:10 CST 2024*/ /* DO NOT EDIT */ grant codeBase "file:/D:/myApp/lib/*" { permission java.security.AllPermission; };
下面命令将打开名为 java.policy 的现有安全策略文件,并允许你编辑其中的策略条目。例如:
policytool -file java.policy
运行效果如下图:
编辑“CodeBase "file:/D:/ProgramFilesFree/Java/jdk1.8.0_45/jre/lib/ext/*"”条目,如下图: