设置扩展权限
如果安全 Manager生效,则必须满足以下条件才能使任何软件(包括扩展软件)执行对安全敏感的操作:
-
extensions 中对安全性敏感的代码必须包装在
PrivilegedAction
对象中。 -
由安全 管理 器实现的安全策略必须向扩展授予适当的权限。默认情况下,已安装的扩展将被授予所有安全权限,就像它们是核心平台 API 的一部分一样。安全策略授予的权限仅适用于
PrivilegedAction
实例中包装的代码。
让我们通过一些示例更详细地研究这些条件。
使用 PrivilegedAction 类
假设您想修改上一课的扩展示例中的RectangleArea
类,以将矩形区域写入文件而不是标准输出。但是,写入文件是对安全性敏感的操作,因此,如果您的软件要在安全性 管理 器下运行,则需要将代码标记为特权。您需要执行两个步骤:
-
您需要将执行安全敏感操作的代码放在类型
java.security.PrivilegedAction
的对象的run
方法中。 -
在调用
java.security.AccessController
的doPrivileged
方法时,必须使用该PrivilegedAction
对象作为参数。
如果我们将这些准则应用于RectangleArea
类,则我们的类定义将如下所示:
import java.io.*;
import java.security.*;
public final class RectangleArea {
public static void
writeArea(final java.awt.Rectangle r) {
AccessController.
doPrivileged(new PrivilegedAction() {
public Object run() {
try {
int area = r.width * r.height;
String userHome = System.getProperty("user.home");
FileWriter fw = new FileWriter( userHome + File.separator
+ "test" + File.separator + "area.txt");
fw.write("The rectangle's area is " + area);
fw.flush();
fw.close();
} catch(IOException ioe) {
System.err.println(ioe);
}
return null;
}
});
}
}
此类中的单个方法writeArea
计算矩形的面积,并将该面积写入用户主目录下test
目录中名为area.txt
的文件中。
处理输出文件的安全性敏感语句放在PrivilegedAction
的新实例的run
方法内。 (注意run
要求返回Object
实例.返回的对象可以是null
.)然后,将新的PrivilegedAction
实例作为参数传递给AccessController.doPrivileged
的调用。
有关使用doPrivileged
的更多信息,请参见 JDK™文档中的特权块的 API。
以这种方式将对安全敏感的代码包装在PrivilegedAction
对象中是使扩展能够执行对安全敏感的操作的首要要求。第二个要求是:使安全 管理 器授予特权代码适当的权限。
使用安全策略指定权限
运行时生效的安全策略由* policy file *指定。默认策略由 JRE 软件中的文件lib/security/java.policy
设置。
该策略文件通过使用* grant *条目为软件分配安全特权。该策略文件可以包含任意数量的授权条目。缺省策略文件具有此授予条目用于已安装的扩展:
grant codeBase "file:${{java.ext.dirs}}/*" {
permission java.security.AllPermission;
};
此项指定由file:${{java.ext.dirs}}/*
指定的目录中的文件将被授予名为java.security.AllPermission
的权限。 (请注意,从 Java 6 开始,java.ext.dirs
指的是类似于classpath
的目录路径,每个目录都可以包含已安装的 extensions.)很难猜测java.security.AllPermission
授予已安装的 extensions 所有可能的安全特权。
然后,默认情况下,已安装的扩展没有安全限制。扩展软件可以执行安全敏感的操作,就好像没有安装安全 管理 器一样,前提是安全敏感代码包含在doPrivileged
调用中作为参数传递的PrivilegedAction
实例中。
要限制授予扩展的特权,您需要修改策略文件。要拒绝所有扩展的所有特权,您只需删除上面的授予条目即可。
并非所有权限都像默认授予的java.security.AllPermission
一样全面。删除默认授权条目后,您可以为特定权限 Importing 新的授权条目,包括:
-
java.awt.AWTPermission
-
java.io.FilePermission
-
java.net.NetPermission
-
java.util.PropertyPermission
-
java.lang.reflect.ReflectPermission
-
java.lang.RuntimePermission
-
java.security.SecurityPermission
-
java.io.SerializablePermission
-
java.net.SocketPermission
JDK 中的权限文档提供了有关每个权限的详细信息。让我们看看使用 RectangleArea 作为扩展所需的内容。
RectangleArea.writeArea
方法需要两个权限:一个用于确定用户主目录的路径,另一个用于写入文件。假设RectangleArea
类 Binding 在文件area.jar
中,则可以通过将此条目添加到策略文件中来授予写特权:
grant codeBase "file:${java.home}/lib/ext/area.jar" {
permission java.io.PropertyPermission "user.home",
"read";
permission java.io.FilePermission
"${user.home}${/}test${/}*", "write";
};
此条 ObjectcodeBase "file:${java.home}/lib/ext/area.jar"
部分保证此条目指定的任何权限仅适用于area.jar
。 java.io.PropertyPermission
允许访问属性。第一个参数"user.home"
命名属性,第二个参数"read"
表示可以读取该属性。 (另一个选择是"write"
.)
java.io.FilePermission
允许访问文件。第一个参数"${user.home}${/}test${/}*"
表示已授予area.jar
权限,以访问用户主目录中test
目录中的所有文件。 (请注意,${/}
是与平台无关的文件分隔符.)第二个参数表示所授予的文件访问权仅用于写入。 (第二个参数的其他选择是"read"
,"delete"
和"execute"
.)
Signing Extensions
您可以使用策略文件通过要求扩展由可信实体签名来对授予扩展的权限进行其他限制。 (有关签名和验证 JAR 文件的 Comment,请参阅本教程中的签名 JAR 文件类。)
要允许对扩展或其他软件进行签名验证以及授予权限,策略文件必须包含* keystore 条目*。密钥库条目指定在验证中使用哪个密钥库。密钥库条目具有以下形式
keystore "keystore_url";
URL * keystore_url *是绝对的或相对的。如果是相对的,则 URL 是相对于策略文件的位置的。例如,要使用keytool
使用的默认密钥库,请将此条目添加到java\.policy
keystore "file://${user.home}/.keystore";
要表示必须对 extensions 进行签名才能获得安全性特权,请使用signedBy
字段。例如,以下条目指示仅当 extensionsarea.jar
由密钥库中由别名 Robert 和 Rita 标识的用户签名时,才被授予列出的特权。
grant signedBy "Robert,Rita",
codeBase "file:${java.home}/lib/ext/area.jar" {
permission java.io.PropertyPermission
"user.home", "read";
permission java.io.FilePermission
"${user.home}${/}test${/}*", "write";
};
如果省略了codeBase
字段(如以下“授予”所示),则将权限授予任何由“ Robert”或“ Rita”签名的软件,包括已安装或下载的 extensions:
grant signedBy "Robert,Rita" {
permission java.io.FilePermission "*", "write";
};
有关策略文件格式的更多详细信息,请参阅 JDK 文档中安全架构规范的 3.3.1 节。