级别: 初级 Paul Everett (everettp@us.ibm.com), 软件工程师, IBM
2001 年 7 月 04 日 Weblet 是运行在浏览器中的 Java 程序,使用 DirectDOM来直接操作被显示的文档。就像大多数基于 Web 的程序一样,如果对Weblet 管理不当,就会对系统安全造成威胁。幸好,Weblet 附带的 Java沙箱(Java Sandbox)可提高系统的内建安全性。在这个关于 DirectDOM和基于 Weblet 开发的三部系列的最后一部分,Paul Everett说明了如何使用沙箱来达到最佳效果。通过简单的工作示例,Paul 演示了Weblet在缺省情况下能做什么和不能做什么,还说明了在需要的情况下如何回避沙箱的约束。
您大概已经对 Applet 沙箱比较熟悉。Applet 与 Weblet
一样是在浏览器中运行的 Java
小程序。它们经常是从未知系统不知不觉地载入您的机器,所以必须保证它们是绝对安全的。缺省情况下,Applet
沙箱是应用到 Applet
的一套限制和许可。沙箱可以保护用户和客户机系统不受低质量程序或恶意
Applet 的侵害。
如果您已经开发过 Applet,那么实现 Weblet
安全性对您来说应该是很直观的。Weblet 与 Applet
有同样的安全隐患,也需要同样的保护。事实上,Weblet 和 Applet
甚至使用同样的沙箱。缺省情况下 Weblet 沙箱禁止 Weblet
执行下列有潜在危险的活动:
- 读文件或写文件
- 启动其它的程序
- 读取某个系统属性
- 关闭 JVM
- 打印
- 访问当前 Java 安全策略
- 通过套接字或 URL 连接服务器而非主机
与 Applet 一样,Weblet
可以在它们的沙箱中非常自由地运行,所以您可以使用它做许多工作,而无需受安全性的约束。在本文中,我将向您说明缺省情况下
Weblet
沙箱是如何工作的,以及您如何在需要的情况下安全地扩展其参数。我们将使用一个示例开始探索
Weblet 安全性。
注意:本文所描述的 Weblet 安全性在写这篇文章时已经在
DirectDOM 的 alphaWorks
版本中得到了实现,请阅读有关文档来查看新的变化和增强的功能(请参阅
参考资料)。
SecurityOps:一个安全性检验程序
SecurityOps 是一个
Weblet,用来尝试几个安全性敏感的操作。我已经在下一章显示了每一个操作(包括异常)的结果。现在开始,可以在
清单 1 中查看这个 Weblet 的
HTML 文件。
现在,让我们来看一下
清单
2 中的
SecurityOps.java 。注意:对于每一个操作都有一个
try/catch 子句和一个已命名的输出区域。
如果编译
SecurityOps.java ,把生成的类放在
SecuritySamples.jar 文件中并载入 HTML 文件,输出将会如
清单 3所示。
只有 2 个操作是成功的:读取
os.name
系统属性和连接到服务主机。稍后,我们将会知道为什么它们会成功。其它的操作都产生了一些不同的
AccessControlException 异常。
沙箱的工作原理
Weblet 在执行时可以访问自己所在的 jar 文件内部的类(在它的 HTML
文件的 WEBLET_CODEBASE
<param>
标记中指定)。除此之外,对 Weblet
的安全性和访问控制的管理还要考虑以下三种情况:
-
DirectDOM 插件调用 SecurityManager。
当运行独立的 Java 程序时,它们通常会毫无限制地运行。如果您使用
-Djava.security.manager 参数调用
java ,您的程序就会在
SecurityManager
的控制下运行。
SecurityManager
会探测到那些可能不太安全可靠的操作并对之进行异常处理。同样,DirectDOM“引擎”会使用
SecurityManager 启动 JVM,这样就实现了沙箱。请参阅
参考资料,以获取更多关于安全管理器和策略文件的信息。
-
java.policy 设置安全策略。
当
SecurityManager
在未经特殊配置的情况下运行时,所有的敏感操作都会产生一个异常;也就是说,所有这样的操作都会被阻塞。如果您想许可一个程序执行这些操作,可以在
java.policy 中创建
grant
语句,
SecurityManager
读入该语句并强制执行。在下一章您会了解到如何通过对 java.policy
进行特殊配置来更改您的 Weblet 安全策略。
-
Weblet 能连接到它们的主机。
与 Applet 一样,缺省情况下 Weblet
能连接到它的主机。与其它系统的连接会被堵塞,但是可以通过
java.policy
允许连接。在谈到连接这个课题时,我们将对此做更多的讨论。
扩展沙箱
在这一章我将向您显示如何通过对 java.policy 文件进行特殊配置来启用
SecurityOps weblet 中的附加操作。在对自己系统中的 java.policy
进行特殊配置时,您最好先学习 Java 2 平台的安全性文档(请参阅
参考资料),并备份您的 java.policy
文件。
清单 4 显示了
java.policy
示例文件的一部分。请仔细看一下,我们将在下面对它进行详细讨论。
关于示例的注意事项
通过浏览这个 java.policy 文件,您会看到几个
grant
语句(尽管最后几句被注释掉了)。每一个
grant
列出一个或多个将被授予一组特殊程序的许可。可通过命名一个 permission
类对这些许可进行定义,这个类是
java.security.Permission 的一个子类。各种 Java API
都提供 permission 类来管理对特定资源的访问。例如:
-
java.net.SocketPermission
控制通过套接字对网络的访问。
-
java.util.PropertyPermission
控制读/写系统属性。
-
java.lang.RuntimePermission
控制运行时的行为,比如对打印作业进行排队。
permission 类可能会需要 java.policy
中的一些参数;细节问题请参阅
参考资料。
被授予许可的程序是通过“codebase”进行定义的,它本质上是一个
URL,Java 类通过它被载入。清单 4
中的第一个(也是最大的一个)
grant 语句没有定义
codebase,所以不管那些程序是从本地文件载入还是通过 Web
载入,列出的许可都被授予
所有的程序。这个
grant
是从缺省 java.policy 中复制过来的,它定义了 Applet、Weblet
以及其它所有在
SecurityManager
控制下运行的类的缺省沙箱。
在这里添加许可要非常小心!
grant
语句授予“看”特定系统属性的许可。例如,列出了
os.name ,SecurityOps
就能载入该属性。没有列出的系统属性就无法获取,这就是为什么试图载入
user.name 时会抛出一个异常。
附加许可
清单 4 显示了三个
grant 语句,这些语句可以启用这个
SecurityOps weblet
中的附加功能。由于它们被注释掉了,所以示例程序初始在缺省的沙箱中运行。在所有这三种情况下,codebase
是由 SecuritySamples.jar 构成。前两种情况适用于 jar
文件从本地磁盘载入的情况。如果把这两句的注释去掉并且对 codebase
进行特殊配置以适合您的安装,您可以启用 SecurityOps weblet
中的“print”和“connect”示例。例如,我的策略文件包含对本地 Weblet
的许可,如清单 5 所示。
清单 5. java.policy:本地
Weblet 的许可
// Enable printing, when loaded from a local file
grant codeBase "file:///e:/everett/article/SecuritySamples.jar" {
permission java.lang.RuntimePermission "queuePrintJob";
};
// Enable a network connection, when loaded from a local file
grant codeBase "file:///e:/everett/article/SecuritySamples.jar" {
permission java.net.SocketPermission "www.ibm.com", "connect,accept,resolve";
};
|
清单 6 显示如何在
grant 语句中授予和清单 5 中相同的两种许可;如果 jar 文件是从服务器载入的,您会用到这种类型的许可。
清单 6.
java.policy:接受服务的 Weblet 许可
// Enable printing and connections, when served by a web server
grant codeBase "http://pwe.endicott.ibm.com/article/SecuritySamples.jar" {
permission java.net.SocketPermission "www.ibm.com",
"connect,accept,resolve";
permission java.lang.RuntimePermission "queuePrintJob";
};
|
当然,必须对 codebase
中定义的特定目录或服务器进行特殊配置以适合您的安装环境。
注意,当 codebase 被作为特定的 jar 文件定义时,
grant 中的 codebase 可以被定义为下面几种类型:
- 一个特定的 jar 文件(本地的或者接受服务的)
- 特定目录中的 jar 文件
- 目录树中的 jar 文件
- 来自特定服务器的 jar 文件
- 带有一个特殊电子签名的 jar 文件
授予许可时最好是定义得尽可能明确。如果一个 Weblet
需要附加的许可,最好是把这个 Weblet 的类隔离到一个专门的 jar
文件中,然后只需对
该 jar
文件授予那些许可即可。这样可以减少无意负面影响的发生机率(也即,为一个特定
Weblet 指定的特权不会被意外地授予其它的代码)。
通过添加附加的许可,可以启用 SecurityOps 中的许多操作。利用
java.policy
文件可以做许多工作,我们只是接触了一些皮毛。有关更多信息,请参阅
参考资料。
关于 SOCKS 代理的论题
如您所见,一个 Weblet
可以在缺省情况下连接到为之服务的服务器。另外,还可以通过对
java.policy 文件进行特殊配置,以授予 Weblet
连接其它系统的许可。到目前为止,Weblet 安全性与 Applet
安全性很相似。但是在这里要指出 Weblet 与 Applet
之间有一个很重要(而且很复杂)的差异。
如果您的浏览器被配置成通过 SOCKS
代理连接到其它的系统,那个代理将会破坏 Weblet
的建立连接的能力。在这样的配置下,所有的连接实际上是连到 SOCKS
代理,此代理代表您建立连接并返回数据。例如,如果您想要连接到“my.home.server.com”,您会看到一个异常报告说您需要连接“
my.socks.proxy”的许可。这是很令人头痛的,但是我们可以设法解决这个问题。
您可以授予您的 Weblet 连接到 SOCK
服务器的许可,但是,在授权的时候,应该仔细限制许可的范围;也就是说,将
grant codebase 限制为
仅需要这种许可的
Weblet。可以连接到 SOCKS 服务器的 Weblet,也可通过 URL
操作连接到其它的系统。所以,给予“所有人”连接 SOCKS
服务器的许可是一个安全隐患。只应该将这种许可授予那些您信任的“人”。清单
7 显示了如何回避 SOCKS。
清单 7. java.policy:回避
SOCKS
// enable sample weblet connections in a SOCKS environment
grant codeBase "file:///e:/everett/article/SecuritySamples.jar" {
permission java.net.SocketPermission "my.socks.proxy", "resolve";
permission java.lang.RuntimePermission "readFileDescriptor";
permission java.lang.RuntimePermission "writeFileDescriptor";
};
|
据说,将来的 JDK 将包含一个改进的 socket factory。这可能是 SOCKS
问题的真正解决方案;目前,我们只能小心(并仔细)地启用 Weblet
以连接到 SOCKS 服务器。
结论
您已经看到了,DirectDOM 被很好的建立来帮助您管理系统的 Weblet
安全性。在本文中,我们已经逐步了解了 DirectDOM
的基本工作原理,如下所述:
- 在启动时,DirectDOM 引擎调用
SecurityManager ,使用
Java 平台的安全性方法实现 Weblet 沙箱。
- DirectDOM 动态地授予 Weblet 的类连接自己的 hosting server
的许可。
- 在缺省的沙箱中被授予的许可是由可应用的 java.policy
文件的内容来控制的。所以,同一个系统中的 Weblet 和 Applet
共享同一个沙箱。
记住这些设置,通过我已经提供的示例,以及 Java
安全性工作的基本知识(请参阅
参考资料),您应该能够开发安全可靠的
Weblet。练习您已经学过的东西 ―
记住仅在必需许可的时候才授予许可,仅对那些需要许可的 Weblet
类授予许可。
参考资料
关于作者  | |  | Paul Everett 在 IBM 在纽约 Endicott 的分部工作,目前是在 DirectDOM
小组。他还有他自己的流程图模板和代码本,但认为这篇 Java
文章会很受欢迎。可以通过
everettp@us.ibm.com 与 Paul
联系。
|
对本文的评价
|