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 )实施了关联。