文档

Java™教程
隐藏目录
为扩展程序设置权限
指南:扩展机制
课程:使扩展安全

为扩展设置权限

如果启用了安全管理器,则必须满足以下条件,以便使任何软件(包括扩展软件)能够执行安全敏感操作:

让我们稍微详细介绍一下这些条件,并提供一些示例。

使用PrivilegedAction类

假设您想要修改上一课程示例中的扩展中的RectangleArea类,将矩形面积写入文件而不是标准输出。然而,写入文件是一个安全敏感操作,所以如果您的软件将在安全管理器下运行,您需要将代码标记为特权代码。您需要执行两个步骤:

  1. 您需要将执行安全敏感操作的代码放在类型为java.security.PrivilegedAction的对象的run方法中。
  2. 您必须使用java.security.AccessControllerdoPrivileged方法的参数来使用该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计算一个矩形的面积,并将面积写入名为area.txt的文件中,该文件位于用户主目录下的test目录中。

处理输出文件的安全敏感语句被放置在新的PrivilegedAction实例的run方法中。(注意,run要求返回一个Object实例。返回的对象可以是null。)然后将新的PrivilegedAction实例作为参数传递给AccessController.doPrivileged的调用中。

有关使用doPrivileged的更多信息,请参阅JDK™文档中的特权块的API

将安全敏感代码包装在PrivilegedAction对象中是启用扩展执行安全敏感操作的第一个要求。第二个要求是:获取安全管理器授予特权代码适当权限。

使用安全策略指定权限

运行时生效的安全策略由一个策略文件指定。默认策略由JRE软件中的文件lib/security/java.policy设置。

策略文件通过使用grant条目为软件分配安全权限。策略文件可以包含任意数量的grant条目。默认策略文件中为已安装的扩展有以下grant条目:

grant codeBase "file:${{java.ext.dirs}}/*" {
    permission java.security.AllPermission;
};

该条目指定file:${{java.ext.dirs}}/*目录中的文件将被授予名为java.security.AllPermission的权限。(请注意,从Java 6开始,java.ext.dirs指的是类似于classpath的目录路径,每个目录可以包含已安装的扩展。)可以猜测java.security.AllPermission授予已安装的扩展所有可能的安全权限。

因此,默认情况下,已安装的扩展没有安全限制。扩展软件可以执行安全敏感操作,就好像没有安装安全管理器一样,前提是安全敏感代码包含在作为doPrivileged调用的参数中的PrivilegedAction实例中。

要限制授予扩展的权限,需要修改策略文件。要拒绝所有扩展的所有权限,可以简单地删除上述grant条目。

并非所有权限都像默认情况下授予的java.security.AllPermission一样全面。在删除默认的grant条目后,可以为特定权限输入新的grant条目,包括:

JDK文档中的权限提供了每个权限的详细信息。让我们看看作为扩展使用RectangleArea所需的权限。

RectangleArea.writeArea方法需要两个权限:一个是确定用户主目录路径的权限,另一个是写入文件的权限。假设RectangleArea类被打包在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";
};

此条目中的codeBase "file:${java.home}/lib/ext/area.jar"部分确保此条目指定的权限仅适用于area.jarjava.io.PropertyPermission允许访问属性。第一个参数"user.home"指定属性名称,第二个参数"read"表示可以读取该属性。(另一个选择是"write"

java.io.FilePermission允许访问文件。第一个参数"${user.home}${/}test${/}*"表示area.jar被授予访问用户主目录中的test目录下所有文件的权限。(注意,${/}是一个与平台无关的文件分隔符)第二个参数表示授予的文件访问权限仅限于写入。(第二个参数的其他选择包括"read""delete""execute"

签名扩展

您可以使用策略文件对扩展程序授予的权限进行额外限制,要求扩展程序必须由可信实体签名。(有关签名和验证JAR文件的概述,请参见本教程中的签署JAR文件课程)

要在授予权限的同时允许扩展程序或其他软件进行签名验证,策略文件必须包含一个密钥库条目。密钥库条目指定要在验证中使用的密钥库。密钥库条目的格式如下:

keystore "keystore_url";

keystore_url是绝对或相对URL。如果是相对URL,则相对于策略文件的位置。例如,要使用keytool使用的默认密钥库,将以下条目添加到java.policy中:

keystore "file://${user.home}/.keystore";

要指示扩展程序必须签名才能被授予安全权限,您可以使用signedBy字段。例如,以下条目指示只有在area.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字段,如下所示的"grant",权限将授予由"Robert"或"Rita"签名的任何软件,包括已安装或下载的扩展软件:

grant signedBy "Robert,Rita" {
    permission java.io.FilePermission "*", "write";  
};

有关策略文件格式的详细信息,请参阅JDK文档中的Security Architecture Specification的3.3.1节。


上一页:使扩展安全
下一页:封装扩展中的包