Java 安全前景
【IT168 技术文档】
“每三家公司中就有一家公司饱受黑客的困扰”, vnunet.com 于 2004 年 3 月 23 日如是报道,该数据来自 PricewaterhouseCoopers 进行的一项调查。不幸的是,这种经历并非少有,而且事实上也并不鲜见。我们都清楚,大量的黑客正等着侵入您的系统。对于其中一些黑客来说,不过是为了获取侵入他人系统的快感。而另外一些黑客则怀有恶意。
不论黑客们的意图如何,作为软件专业人员——无论是架构师、开发人员还是管理人员——创建安全的、能够防止黑客行为(或者说对黑客不友好)的解决方案是我们共同的职责。本文将探讨一些应用程序安全性方面的问题,并从高层面上讨论 Java 如何以及在哪些地方适用于混合环境,从而使您能够利用其安全性功能来构建安全的架构。
探讨系统安全性
系统安全性是一个复杂的主题,涉及到许多相关的领域。例如,考虑一台位于公共区域、提供给公众访问的计算机。无论您在它上面安置多少警铃,它依然处于被黑客攻击的危险之中。换句话说,您不会想在这台计算机上计算每年的税额。另一方面,考虑一台位于银行室内、没有磁盘驱动器(软盘、 CD 或 DVD )或网络连接的计算机。对这台计算机进行黑客攻击是不可想像的事情。物理上的安全性只是计算机安全性的一个领域。
另一个领域是程序上的 / 操作上的,它包含了如何维护与安全性相关的信息。例如,如果将密码写在纸上,或者在您的键盘上敲出来,那么即使是最有创意的密码也是不保险的。最后,甚至政府也在保护您的系统中扮演着重要角色,因为政府可以制定、实施和执行与惩罚黑客相关的适用法律。
当大多数人考虑系统安全性的时候,他们会想到一些组件,比如防火墙和代理服务器,或者是安全套接字层( Secure Sockets Layer , SSL )这样的协议。尽管这些对于安全性很重要,但是它们无法始终保证系统的安全性。这些协议的首要功能是使外部人员呆在他们应该呆的地方——外部。统计数据已经反复表明,大多数黑客行为出现在内部。为了避免这些类型的攻击,设计应用程序的架构时必须考虑安全性。
Java 平台中的安全性
Java 平台是创建企业应用程序的普遍选择。它之所以如此受欢迎,主要原因之一是在创建 Java 语言时充分考虑了安全性,而且市场普遍认为 Java 是一种“安全的”语言。尽管从各大厂商(如 Microsoft )的 Java 实现中已经找出了一些安全缺陷,但 Java 中提供安全性的架构部分已经得到了时间的检验。 Java 平台在两个层次上提供安全性:语言层次和企业层次。
语言安全特性
如上所述,创建 Java 时已经充分考虑到了安全性,而且 Java 这些年来已经逐渐成熟。以下组件组成了 Java 在语言层次上的安全性:
Java 类加载器
编写 Java 程序所得到的是一些源代码文件的集合,每个源代码文件都有一个或多个类定义。然后,这些源代码文件被编译为字节码( .class )文件,并且可能被打包为 Java 存档文件( Java Archive , JAR )。 Java 代码在 Java 虚拟机( Java Virtual Machine , JVM )中执行,而 Java 虚拟机通常是使用针对特定平台(比如 Windows 或 Solaris )的某种语言(比如 C )编写的。 JVM 在运行期间使用一系列类加载器来加载字节码。为了确保在初始创建字节码(在编译期间)和加载这些字节码来执行它们这段时间之间,字节码没有被篡改,类加载器会从以下方面检查被装入的字节码:
- 装入的字节码没有生成指针。
- 装入的字节码没有违反访问限制。
- 装入的字节码把对象当作它们本身来访问(例如, InputStream 对象总是被用作 InputStream ,永远不会被用作其他的什么)
这个过程被称为“字节码验证”,它在确保执行代码的安全性方面至关重要。类加载器是 Java 安全性的守护者,所以 Java 要采取一些预防措施来确保类加载器机制不会受到损害。这包括下面两项安全措施:
- Java 应用程序需要特殊的权限才能在 JVM 中创建和安装新的类加载器(在 JVM 提供的类加载器之外)。
- 所有类加载器必须授权给它们的父加载器,以确保以前加载的类,比如核心的 Java API 类,不会被恶意代码所替换。
类加载器非常依赖于 Java 安全架构的其他两个部分,我们接下来将对这两个部分进行讨论。
安全管理器
在 Java 1.2 以前,安全管理器负责在 JVM 中实施所有的安全策略。这些策略是基于一定的标准实施的,比如当前的类深度或当前的类加载器深度。现在,已经不鼓励使用这些方法。随着版本 1.2 的引入,安全管理器把许多安全策略的实施工作委托给了一个叫做访问控制器的新组件,该组件支持更加丰富多样和更加灵活的安全策略。
访问控制器
访问控制器的引入导致了 Java 中的一些新概念的引入,比如权限、策略、代码源和保护域。每个 Java 1.2 应用程序都与一个代码源相关联,该代码源决定了代码的来源。在这个代码源的基础上,应用程序被授予(或拒绝授予)一组权限。策略封装了每个代码源及其权限集之间的关联(或映射)。每个这样的关联 / 映射被称为一个保护域。因此,策略就是一些保护域的集合。
归根结底,访问控制器提供了三个主要用途:
- 基于当前有效的安全策略,决定允许对关键系统资源进行访问,还是拒绝这类访问。
- 支持标记代码特权化,因而影响到了随后的访问确定。
- 获得当前调用上下文的“快照”,这样可以根据保存的上下文,制定出来自不同上下文的访问控制决策。
企业安全特性
迄今为止,我已经陈述了 Java 的内置安全特性。默认情况下,所有 Java 应用程序都继承了这些特性,但是一些应用程序可能比其他应用程序更能很好地利用这些特性。 Java 平台还提供其他 API/ 功能,以便为企业应用程序提供一个总体的安全性解决方案。我将在这里列出这些解决方案,并简要介绍它们。
Java 加密扩展( JCE )
JCE 是一组包,为加密、密钥生成、密钥协商和消息身份验证代码( Message Authentication Code ,MAC )算法提供一种框架和实现。 JCE 支持多种类型的加密,包括对称的、非对称的、块和流密码。在 Java 1.4 之前, JCE 是一个可选的包,但是现在,它已经成为 Java 平台的一个标准组成部分。
Java 安全套接字扩展( JSSE )
JSSE 是支持安全的 Internet 通信的一组包。它实现了 SSL 和传输层安全( Transport Layer Security , TLS )协议的 Java 技术版本。它包括用于数据加密、服务器身份验证、消息完整性和可选的客户端身份验证的诸多功能。与 JCE 一样, JSSE 已经被集成到 1.4 以上版本的 Java 平台中。
Java 命名和目录接口( JNDI )
JNDI 是 Java 技术中特有的一个 API ,用于给使用 Java 编程语言编写的应用程序提供命名和目录功能。它是使用 Java 的对象模型特地为 Java 平台而设计的。使用 JNDI ,基于 Java 技术的应用程序就可以保存和获取任意类型的 Java 对象。 JNDI 目录中的每个对象都可以得到保护。这意味着:访问对这类对象的引用的用户需要提供他们的证书,而 JNDI 实现会检验这些证书。 Java 应用服务器广泛使用 JNDI 来保存到 Enterprise JavaBean ( EJB )实例、 Java 消息服务( Java Message Service , JMS )队列和 Java 数据库连接( Java Database Connectivity , JDBC )数据源(数据库连接)的引用。
Java 身份验证和授权规范( JAAS )
在引入 JAAS 之前, Java 的内置安全性基于 JVM 的代码的起源地。而没有考虑“谁”来执行代码。但是代码执行中的“谁”是很重要的一个考虑事项,因为您可能想基于这个“谁”来控制程序的功能。 JAAS 扩展了 Java 现有的安全基础架构,从而克服了这个缺点。
JAAS 身份验证组件能够可靠而安全地确定当前是谁正在执行 Java 代码,无论代码是作为应用程序、 applet 、 bean 还是作为 servlet 来运行的。 JAAS 身份验证组件对现有的 Java 2 安全框架进行了补充,具体做法是通过提供一些方法限制执行敏感任务的 Java 代码的执行,这不仅取决于任务的起源,还取决于通过身份验证的用户。 JAAS 身份验证是以可插入的方式执行的,这允许 Java 应用程序保持与底层身份验证技术之间的独立。因此,可以在应用程序中插入新的或者经过更新的身份验证技术,同时无需修改应用程序本身。最后,与 JCE 及 JSSE 一样, JAAS 已经被集成到 1.4 以上版本的 Java 平台中。在“ All That JAAS ”( Java Pro )中可以参阅更多与 JAAS 有关的内容。
Web 应用程序安全
Web 应用程序安全构建在核心 Java 语言安全性之上,以便给表示层组件提供一个额外的安全层。 Web 应用程序安全可以在两种模式下使用:声明模式和编程模式。这两种模式都支持“角色”与 Web 资源(比如 servlets 和 JavaServer Pages ( JSP ))的关联。角色类似于您的计算机操作系统(比如 Windows XP )中的组,这意味着一个角色就是一个用户集。在一个操作系统中,组允许您在宏观级别上控制对系统资源的访问。例如,可以允许 Human Resources 组中的所有用户访问工资表。在声明性的安全中,角色与 Web 资源之间的关联是在 Web 部署描述符( web.xml )中实现的。编程性的安全通过使用由 Java servlet 规范指定的方法调用( getRemoteUser , getCallerPrincipal 和 isCallerInRole ),在 Web 资源自身中实施了角色与 Web 资源之间的关联。
EJB 安全
与 Web 应用程序安全类似, EJB 安全构建在核心的 Java 语言安全性上,以便给业务对象提供一个额外的安全层。同样,类似于 Web 应用程序安全, EJB 安全也可以在声明模式和编程模式下使用。这两种模式都支持将角色与 EJB 中的方法关联。在声明性安全中,角色 / 方法关联是在应用程序部署描述符( ejb-jar.xml )和一个特定于应用服务器的部署描述符中实现的。编程性安全使用由 EJB 规范指定的方法调用( getCallerPrincipal and isCallerInRole )实施了关联。
自由联盟(和 Web 服务安全)
自由联盟计划( Liberty Alliance project )始于 2001 年 9 月,旨在为联合身分管理( federated identity management )及相关服务建立一种开放的标准。在本文中,这个项目的重要性在于 Sun Microsystems 是自由联盟的创始成员之一。自由联盟的理事会现在还包括其他的 13 家公司,比如 American Express 、 HP 、 Nokia 、 Sony 、 GM ,等等,还有大量成员公司成为了自由联盟的发起人、合作人和会员。
联盟的主要成果是一种联盟网络身分架构,以及为想要创建基于创新性身分的 Web 服务的企业提供技术蓝图的规范。
- 对于使用基于 Web 的服务感兴趣的用户被称为 首要用户 ( principal ) , 包括人员和系统用户 。
- 服务提供者提供一组首要用户想要使用的服务(比如预订飞机票)。
- 身份提供者为服务提供者提供证书,以便对首要用户进行身份验证。
该架构还描述了一个过程,该过程允许首要用户进行单点登录( sign-on , SSO )和单点注销。 SSO 允许用户在 Liberty 支持的站点(或者服务提供者)处进行一次登录,这种登录是无缝的,当导航到另一个 Liberty 支持的站点时,无需再次进行身份验证。单点注销提供跨越特定的身分提供者验证的所有会话的同步会话注销功能。
另外,该架构还定义了信赖圈( circle of trust )的概念,它是具有基于 Liberty 架构和操作协议的业务关系的服务提供者和身分提供者的联合,用户们可以通过它们在一种安全而且显然无缝的环境中处理业务。最后,该架构描述了安全性断言标记语言( Security Assertion Markup Language , SAML ),这是一种 OASIS 标准,用于在服务和身分提供者之间交互与安全相关的信息(称为断言)。
在本文中,我从概要描述围绕系统安全性的很多问题开始。然后,我从高层次探讨了 Java 平台上这个难题的各个部分,以便帮助您创建安全的架构。记住,没有什么比使用 Java ,放置合适的防火墙和代理服务器,并使用 SSL 进行通信能够提供更多的系统安全性。设计应用程序的架构时就要考虑到安全性方面的问题,这样才能设计出安全的应用程序。