大多数 Java 应用程序都需要某种类实例级的访问控制。例如,基于 Web 的、自我服务的拍卖应用程序的规范可能有下列要求:
任何已注册(经过认证)的用户都可以创建一个拍卖,但只有创建拍卖的用户才可以修改这个拍卖。
这意味着任何用户都可以执行被编写用来创建 Auction 类实例的代码,但只有拥有该实例的用户可以执行用来修改它的代码。通常情况下,创建 Auction 实例的用户就是所有者。这被称为 类实例所有者关系(class instance owner relationship)。
该应用程序的另一个要求可能是:
任何用户都可以为拍卖创建一个投标,拍卖的所有者可以接受或拒绝任何投标。
再一次,任何用户都可以执行被编写用来创建 Bid 类实例的代码,但只有拥有该实例的用户会被授予修改该实例的许可权。而且, Auction 类实例的所有者必须能够修改相关的 Bid 类实例中的接受标志。这意味着在 Auction 实例和相应的 Bid 实例之间有一种被称为 特定关系(special relationship)的关系。
不幸的是,“Java 认证和授权服务”(JAAS)― 它是 Java 2 平台的一部分 ― 没有考虑到类实例级访问控制或者特定关系。在本文中,我们将扩展 JAAS 框架使其同时包含这两者。推动这种扩展的动力是允许我们将访问控制分离到一个通用的框架,该框架使用基于所有权和特定关系的策略。然后管理员可以在应用程序的生命周期内更改这些策略。
在深入到扩展 JAAS 框架之前,我们将重温一下 Java 2 平台的访问控制机制。我们将讨论策略文件和许可权的使用,并讨论 SecurityManager 和 AccessController 之间的关系。
Java 2 平台中的访问控制
在 Java 2 平台中,所有的代码,不管它是本地代码还是远程代码,都可以由策略来控制。 策略(policy)由不同位置上的代码的一组许可权定义,或者由不同的签发者定义、或者由这两者定义。 许可权允许对资源进行访问;它通过名称来定义,并且可能与某些操作关联在一起。
抽象类 java.security.Policy 被用于表示应用程序的安全性策略。缺省的实现由 sun.security.provider.PolicyFile 提供,在 sun.security.provider.PolicyFile 中,策略被定义在一个文件中。清单 1 是一个典型策略文件示例:
清单 1. 一个典型的策略文件
// Grant these permissions to code loaded from a sample.jar file
// in the C drive and if it is signed by XYZ
grant codebase "file:/C:/sample.jar", signedby "XYZ" {
// Allow socket actions to any host using port 8080
permission java.net.SocketPermission "*:8080", "accept, connect,
listen, resolve";
// Allows file access (read, write, execute, delete) in
// the user's home directory.
Permission java.io.FilePermission "${user.home}/-", "read, write,
execute, delete";
};
SecurityManager 对 AccessController
在标准 JDK 分发版中,控制代码源访问的机制缺省情况下是关闭的。在 Java 2 平台以前,对代码源的访问都是由 SecurityManager 类管理的。 SecurityManager 是由 java.security.manager 系统属性启动的,如下所示:
java -Djava.security.manager
在 Java 2 平台中,可以将一个应用程序设置为使用 java.lang.SecurityManager 类或者 java.security.AccessController 类管理敏感的操作。 AccessController 在 Java 2 平台中是新出现的。为便于向后兼容, SecurityManager 类仍然存在,但把自己的决定提交 AccessController 类裁决。 SecurityManager 和 AccessController 都使用应用程序的策略文件确定是否允许一个被请求的操作。清单 2 显示了 AccessController 如何处理 SocketPermission 请求:
清单 2. 保护敏感操作
Public void someMethod() {
Permission permission =
new java.net.SocketPermission("localhost:8080", "connect");
AccessController.checkPermission(permission);
// Sensitive code starts here
Socket s = new Socket("localhost", 8080);
}
在这个示例中,我们看到 AccessController 检查应用程序的当前策略实现。如果策略文件中定义的任何许可权暗示了被请求的许可权,该方法将只简单地返回;否则抛出一个 AccessControlException 异常。在这个示例中,检查实际上是多余的,因为缺省套接字实现的构造函数也执行相同的检查。
在下一部分,我们将更仔细地看一下 AccessController 如何与 java.security.Policy 实现共同合作安全地处理应用程序请求。
查看原文>>
http://www.ibm.com/developerworks/cn/java/j-jaas/
(责任编辑:云子)