赞
踩
Java 安全包括大量 API、工具以及常用安全算法、机制和协议的实现。Java 安全 API 涵盖了广泛的领域,包括加密、公钥基础设施、安全通信、身份验证和访问控制。Java 安全技术为开发人员提供了编写应用程序的全面安全框架,还为用户或管理员提供了一组工具来安全地管理应用程序。
JDK 的设计非常注重安全性。从本质上讲,Java 语言本身是类型安全的,并提供自动垃圾收集功能,从而增强了应用程序代码的稳健性。安全的类加载和验证机制可确保仅执行合法的 Java 代码。Java 安全架构包括大量应用程序编程接口 (API)、工具以及常用安全算法、机制和协议的实现。
Java 安全 API 涉及领域广泛。加密和公钥基础设施 (PKI) 接口为开发安全应用程序提供了基础。执行身份验证和访问控制的接口使应用程序能够防止未经授权访问受保护的资源。
这些 API 允许多种可互操作的算法实现和其他安全服务。服务以以下方式实现:providers这些安全服务通过标准接口插入到 JDK 中,使应用程序可以轻松获取安全服务,而无需了解其实现。这使开发人员可以专注于如何将安全性集成到应用程序中,而不是如何实际实现复杂的安全机制。
JDK 包含许多实现一组核心安全服务的提供程序。它还允许安装其他自定义提供程序。这使开发人员能够使用新的安全机制扩展平台。
JDK 分为多个模块。包含安全 API 的模块包括:
模块 | 描述 |
---|---|
java.base | 定义Java SE的基础 API ;所含的包包括 java.security,javax.crypto,javax.net.ssl, 和javax.security.auth |
java.security.jgss | 定义 IETF 通用安全服务 API (GSS-API) 的 Java 绑定。此模块还包含 GSS-API 机制,包括 Kerberos v5 和 SPNEGO |
java.security.sasl | 定义 Java 对 IETF 简单身份验证和安全层 (SASL) 的支持。此模块还包含 SASL 机制,包括 DIGEST-MD5、CRAM-MD5 和 NTLM |
java.smartcardio | 定义 Java 智能卡 I/O API |
java.xml.crypto | 定义 XML 加密的 API |
jdk.jartool | 定义用于签名 jar 文件的 API |
jdk.security.auth | 提供以下实现javax.security.auth.*接口及各类认证模块 |
jdk.security.jgss | 定义 GSS-API 的 Java 扩展和 SASL GSS-API 机制的实现 |
Java 语言旨在确保类型安全且易于使用。它提供自动内存管理、垃圾收集和数组范围检查。这减轻了开发人员的总体编程负担,减少了细微的编程错误,并提高了代码的安全性和稳定性。
编译器将 Java 程序转换为与机器无关的字节码表示。调用字节码验证器来确保在 Java 运行时中仅执行合法的字节码。它检查字节码是否符合 Java 语言规范,并且不违反 Java 语言规则或命名空间限制。验证器还会检查是否存在内存管理违规、堆栈下溢或溢出以及非法数据类型转换。验证字节码后,Java 运行时会准备执行它们。
此外,Java 语言还定义了不同的访问修饰符,可以将其分配给 Java 类、方法和字段,从而使开发人员能够根据需要限制对其类实现的访问。该语言定义了四种不同的访问级别:
JDK 定义了一组涵盖主要安全领域的 API,包括加密、公钥基础设施、身份验证、安全通信和访问控制。这些 API 允许开发人员轻松地将安全性集成到其应用程序代码中。
API 的设计遵循以下原则:
实现独立(Implementation Independence)
应用程序无需自行实现安全性。相反,它们可以从 JDK 请求安全服务。安全服务在提供程序中实现(请参阅安全提供程序部分),这些提供程序通过标准接口插入 JDK。应用程序可以依赖多个独立的提供程序来实现安全功能。
实现互操作性(Implementation interoperability)
提供程序可跨应用程序互操作。具体而言,如果应用程序不依赖提供程序的默认值,则不会绑定到特定提供程序。
算法可拓展(Algorithm extensibility)
JDK 包含许多内置提供程序,它们实现了目前广泛使用的一组基本安全服务。但是,某些应用程序可能依赖于尚未实现的新兴标准或专有服务。JDK 支持安装实现此类服务的自定义提供程序。
该类java.security.Provider封装了 Java 平台中的安全提供程序的概念。它指定提供程序的名称并列出其实现的安全服务。可以同时配置多个提供程序,并按优先顺序列出。当请求安全服务时,将选择实现该服务的最高优先级提供程序。
应用程序依靠相关getInstance方法向底层提供商请求安全服务。
例如,消息摘要创建代表提供商提供的一种服务。要请求特定消息摘要算法的实现,请调用方法java.security.MessageDigest.getInstance以下语句请求 SHA-256 消息摘要实现而不指定提供者名称:
MessageDigest md = MessageDigest.getInstance("SHA-256");
下图说明了此语句如何获取 SHA-256 消息摘要实现。按优先顺序搜索提供商,并ProviderC返回提供该特定算法的第一个提供商的实现。
说明
您可以选择通过指定提供商的名称来请求特定提供商的实现。
Oracle 的 Java 平台实现包含许多内置默认提供程序,这些提供程序实现了一组可供应用程序使用的基本安全服务。请注意,Java 平台的其他供应商实现可能包含不同的提供程序集,这些提供程序集封装了特定于供应商的安全服务集。术语“内置默认提供程序”是指 Oracle 实现中可用的提供程序。
下表列出了一些与安全相关的文件和工具的位置。
文件名或工具名称 | 位置 | 描述 |
---|---|---|
java.security | /conf/security | Java 安全性的某些方面(例如配置提供程序)可通过设置安全属性进行自定义。您可以在文件中静态设置安全属性java.security。还可以通过调用Security类(在 java.security包中)的适当方法来动态设置安全属性。 |
java.policy | /conf/security | 这是默认的系统策略文件;请参阅安全策略。 |
加密策略目录 | /conf/security/policy | 该目录包含多组管辖权策略文件;请参阅加密强度配置。 |
cacerts | /lib/security | 该cacerts 文件代表包含证书颁发机构 (CA) 和其他受信任证书的系统范围密钥库。有关配置和管理此文件的信息,请参阅Java 平台标准版工具参考中的keytool。 |
keytool, jarsigner仅限 Windows : kinit,,klistktab | /bin | 有关安全相关工具的更多信息,请参阅Java 平台标准版工具参考中的安全工具和命令。 |
Java 加密架构是用于访问和开发 Java 平台加密功能的框架。
它包括各种加密服务的 API,其中包括:
由于历史(出口管制)原因,加密 API 被组织成两个不同的包:
java.security包和java.security.*包含以下类不会受到出口管制(如Signature和MessageDigest)
该javax.crypto软件包中包含受出口管制的类别(如Cipher和KeyAgreement)
加密接口基于提供程序,允许多种可互操作的加密实现。一些提供程序可能在软件中执行加密操作;其他提供程序可能在硬件令牌上执行操作(例如,在智能卡设备或硬件加密加速器上)。实施出口管制服务的提供程序必须由 Oracle JCE 证书颁发机构颁发的证书进行数字签名。
Java 平台包含许多最常用加密算法的内置提供程序,包括 RSA、DSA 和 ECDSA 签名算法、AES 加密算法、SHA-2 消息摘要算法以及 Diffie-Hellman (DH) 和椭圆曲线 Diffie-Hellman (ECDH) 密钥协议算法。大多数内置提供程序都以 Java 代码实现加密算法。
Java 平台还包括一个内置提供程序,可充当本机 PKCS#11 (v2.x) 令牌的桥梁。此提供程序名为SunPKCS11,允许 Java 应用程序无缝访问位于符合 PKCS#11 标准的令牌上的加密服务。
在 Windows 上,Java 平台包含一个内置提供程序,可充当本机 Microsoft CryptoAPI 的桥梁。此提供程序名为SunMSCAPI,允许 Java 应用程序通过 CryptoAPI 无缝访问 Windows 上的加密服务。
公钥基础设施 (PKI) 是指基于公钥加密技术实现信息安全交换的框架。它允许将身份(个人、组织等)绑定到数字证书,并提供验证证书真实性的方法。PKI 包括密钥、证书、公钥加密和生成证书并进行数字签名的可信认证机构 (CA)。
Java 平台包括对 X.509 数字证书和证书吊销列表 (CRL) 的 API 和提供程序支持,以及符合 PKIX 的证书路径构建和验证。与 PKI 相关的类位于和java.security包中java.security.cert。
Java 平台通过密钥和证书存储提供加密密钥和证书的长期持久存储。具体来说, 类java.security.KeyStore表示密钥存储,即加密密钥和/或受信任证书(例如,在认证路径验证期间使用)的安全存储库,而 类java.security.cert.CertStore表示证书存储,即不相关且通常不受信任的证书的公共且可能庞大的存储库。CertStore还可以存储 CRL。
KeyStore和CertStore实现通过类型来区分。Java 平台包括标准 PKCS11 和 PKCS12 密钥存储类型(其实现符合 RSA Security 的相应 PKCS 规范)。它还包含一种专有的基于文件的密钥存储类型,称为 JKS(代表 Java 密钥存储),以及一种称为 DKS(域密钥存储)的类型,它是密钥存储的集合,以单个逻辑密钥存储的形式呈现。
Java 平台包含一个特殊的内置密钥存储区,cacerts其中包含许多知名、受信任 CA 的证书。keytool 实用程序能够列出 中包含的证书cacerts。请参阅Java 平台标准版工具参考中的keytool。
Java 密码术部分中提到的 SunPKCS11 提供程序包含 PKCS11KeyStore实现。这意味着 Java 应用程序可以通过 API 访问和使用安全硬件(如智能卡)中的密钥和证书KeyStore。请注意,智能卡密钥可能不允许离开设备。在这种情况下, APIjava.security.Key返回的对象KeyStore可能只是对密钥的引用(即,它不包含实际的密钥材料)。这样的对象Key只能用于在实际密钥所在的设备上执行加密操作。
Java 平台还包括 LDAP 证书存储类型(用于访问存储在 LDAP 目录中的证书),以及内存集合证书存储类型(用于访问对象中管理的证书java.util.Collection)。
有两个内置工具可用于处理密钥、证书和密钥存储:
keytool创建和管理密钥库。使用它来执行以下任务:
jarsigner签署 JAR 文件并验证已签署 JAR 文件的签名。Java ARchive (JAR) 文件格式允许将多个文件捆绑为一个文件。通常,JAR 文件包含与小程序和应用程序相关的类文件和辅助资源。
要对代码进行数字签名,请执行以下操作:
用于keytool生成或导入适当的密钥和证书到您的密钥库中(如果它们还不存在)。
使用该jar工具将代码打包成JAR文件。
使用jarsigner工具(或jdk.security.jarsignerAPI) 来对 JAR 文件进行签名。该jarsigner工具访问密钥存储区以查找对 JAR 文件进行签名或验证已签名 JAR 文件的签名所需的任何密钥和证书。
注:jarsigner可以选择性地生成包含时间戳的签名。验证 JAR 文件签名的系统可以检查时间戳并接受在签名证书有效期间签名的 JAR 文件,而不必要求证书是最新的。(证书通常每年到期一次,因此要求 JAR 文件创建者每年重新签署已部署的 JAR 文件是不合理的。)
请参阅Java 平台标准版工具参考中的keytool和jarsigner。
身份验证是确定用户身份的过程。在 Java 运行时环境中,它是识别正在执行的 Java 程序的用户的过程。在某些情况下,此过程可能依赖于 Java加密部分中描述的服务。
Java 平台提供了 API,使应用程序能够通过可插入登录模块执行用户身份验证。应用程序调用该类LoginContext(在javax.security.auth.login包中),该类又引用配置。该配置指定要使用哪个登录模块(接口的实现javax.security.auth.spi.LoginModule)来执行实际身份验证。
由于应用程序仅与标准LoginContextAPI 通信,因此它们可以独立于底层插件模块。可以为应用程序插入新的或更新的模块,而无需修改应用程序本身。下图说明了应用程序与底层登录模块之间的独立性:
说明:
需要注意的是,尽管登录模块是可配置到 Java 平台中的可插入组件,但它们并非通过安全提供程序插入。因此,它们不遵循安全提供程序部分中描述的提供程序搜索模型。相反,如图1-3所示,登录模块由其自己独特的配置进行管理。
Java 平台提供了以下内置登录模块,均在com.sun.security.auth.module包中:
身份验证还可以在两个对等体之间建立安全通信通道的过程中实现。Java 平台提供了许多标准通信协议的实现,这些协议将在“安全通信”一节中讨论。
通过网络传输的数据可能会被非预期接收者访问。当数据包含私人信息(如密码和信用卡号)时,必须采取措施使未经授权的人员无法理解数据。确保将数据发送给适当的人员,并确保数据在传输过程中没有被有意或无意地修改,这一点也很重要。
密码学是安全通信所需的基础;请参阅Java 密码学部分。Java 平台还为许多标准安全通信协议提供 API 支持和提供程序实现。
传输层安全性 (TLS) 及其前身安全套接字层 (SSL) 是加密协议,可在两个通信对等方之间提供安全通道。TLS 使用多种加密过程,为通过不受信任或潜在敌对网络进行的通信提供身份验证、机密性和完整性属性。TLS 在可靠的面向流的传输通道(通常是传输控制协议 (TCP))上运行。TLS 独立于应用程序协议。更高级别的协议(例如超文本传输协议 (HTTP))可以透明地分层在 TLS 之上。
数据报传输层安全性 (DTLS) 协议基于面向流的 TLS 协议,旨在为数据报传输提供类似的安全属性,例如用户数据报协议 (UDP),它不提供可靠或按序的数据传输。
JDK 提供 API 以及 SSL、TLS 和 DTLS 协议的实现,其中包括数据加密、消息完整性以及服务器和客户端身份验证功能。应用程序可以使用 (D)TLS 通过任何应用程序协议(例如 TCP/IP 之上的 HTTP)在两个对等体之间提供安全的数据传递。
此类javax.net.ssl.SSLSocket表示在普通流套接字 ( ) 之上封装 TLS 支持的网络套接字java.net.Socket。某些应用程序可能希望使用备用数据传输抽象(例如 New-I/O);该类javax.net.ssl.SSLEngine可用于生成和使用 TLS/DTLS 数据包。
JDK 还包括支持可插入(基于提供者)密钥管理器和信任管理器概念的 API。A key manager由类封装javax.net.ssl.KeyManager,并管理用于执行身份验证的密钥。trust manager由TrustManager类封装(在同一个包中),并根据它管理的密钥库中的证书来决定信任谁。
JDK 包含一个实现 SSL/TLS/DTLS 协议的内置提供程序:
简单身份验证和安全层 (SASL) 是一种 Internet 标准,它指定了身份验证协议以及在客户端和服务器应用程序之间建立安全层的可选方法。SASL 定义了如何交换身份验证数据,但本身并不指定该数据的内容。它是一个框架,可以容纳指定身份验证数据内容和语义的特定身份验证机制。Internet 社区为各种安全级别和部署方案定义了许多标准 SASL 机制。
Java SASL API,位于java.security.sasl模块,为使用 SASL 机制的应用程序定义类和接口。它被定义为与机制无关;使用该 API 的应用程序无需强制使用任何特定的 SASL 机制。应用程序可以根据所需的安全功能选择要使用的机制。该 API 支持客户端和服务器应用程序。该类javax.security.sasl.Sasl用于创建SaslClient和SaslServer对象。
SASL 机制实现在提供程序包中提供。每个提供程序可能支持一个或多个 SASL 机制,并通过标准提供程序架构进行注册和调用。
Java 平台包含一个内置提供程序,它实现了以下 SASL 机制:
Java 平台包含一个 API,该 API 具有通用安全服务应用程序编程接口 (GSS-API) 的 Java 语言绑定,该接口位于模块中java.security.jgss。GSS-API 为应用程序程序员提供了对各种底层安全机制之上的安全服务的统一访问。Java GSS-API 当前需要使用 Kerberos v5 机制,而 Java 平台包含此机制的内置实现。目前,无法插入其他机制。
注:身份验证Krb5LoginModule部分中提到的可以与 GSS Kerberos 机制结合使用。
Java 平台还包括简单且受保护的 GSS-API 协商机制 (SPNEGO) GSS-API 机制的内置实现。
在两个应用程序可以使用 GSS-API 安全地交换消息之前,它们必须建立联合安全上下文。上下文封装了共享的状态信息,例如,可能包括加密密钥。两个应用程序都创建并使用一个org.ietf.jgss.GSSContext对象来建立和维护构成安全上下文的共享信息。建立安全上下文后,即可使用它来准备要交换的安全消息。
Java GSS API 位于org.ietf.jgss包中。Java 平台还定义了基本 Kerberos 类,例如KerberosPrincipal、KerberosTicket、KerberosKey和KeyTab,它们位于javax.security.auth.kerberos包中。
Java 平台中的访问控制架构保护对敏感资源(例如本地文件)或敏感应用程序代码(例如类中的方法)的访问。所有访问控制决策均由安全管理器(由类表示)进行调解java.lang.SecurityManager。必须将 ASecurityManager安装到 Java 运行时中才能激活访问控制检查。
默认情况下,通过java命令执行的本地应用程序不会在SecurityManager安装的情况下运行。为了使用 运行本地应用程序SecurityManager,应用程序本身必须通过setSecurityManager方法(在java.lang.System类中)以编程方式设置一个,或者java必须-Djava.security.manager在命令行上使用参数调用。
权限代表对系统资源的访问。为了允许小程序(或使用安全管理器运行的应用程序)访问资源,必须向尝试访问的代码明确授予相应的权限。
当 Java 代码由类加载器加载到 Java 运行时时,类加载器会自动将以下信息与该代码关联:
无论代码是通过不受信任的网络下载(例如,小程序)还是从文件系统加载(例如,本地应用程序),此信息都与代码相关联。加载代码的位置由 URL 表示,代码签名者由签名者的证书链表示,默认权限由java.security.Permission对象表示。
自动授予下载代码的默认权限包括与代码来源主机建立网络连接的能力。自动授予从本地文件系统加载的代码的默认权限包括从代码来源目录及其子目录读取文件的能力。
请注意,在类加载时无法获得执行代码的用户身份。如有必要,应用程序代码负责对最终用户进行身份验证(请参阅身份验证doAs部分)。一旦用户通过身份验证,应用程序就可以通过javax.security.auth.Subject调用类中的方法动态地将该用户与执行代码关联起来。
类加载器会为代码授予一组有限的默认权限。管理员可以通过安全策略灵活地管理其他代码权限。
Java SE将安全策略的概念封装在类中。在任何给定时间,java.security.Policy只有一个 对象安装到 Java 运行时中。对象的基本职责是确定是否允许代码访问受保护的资源(以从何处加载、谁对其进行了签名以及谁在执行它为特征)。对象如何 做出此决定取决于实现。例如,它可以查阅包含授权数据的数据库,也可以联系其他服务。 PolicyPolicyPolicy
Java SE包含一个默认 Policy实现,它从安全属性文件中配置的一个或多个 ASCII (UTF-8) 文件中读取其授权数据。这些策略文件包含授予代码的确切权限集:具体而言,授予从特定位置加载、由特定实体签名并以特定用户身份执行的代码的确切权限集。每个文件中的策略条目必须符合记录的专有语法,并且可以通过简单的文本编辑器编写。
Java 运行时会跟踪程序执行过程中的 Java 调用序列。当请求访问受保护的资源时,默认情况下会评估整个调用堆栈以确定是否允许请求的访问。
如前所述,资源受到 的保护SecurityManager。JDK 和应用程序中的安全敏感代码通过以下代码保护对资源的访问:
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(perm);
}
这Permission对象perm对应于所请求的访问权限。例如,如果尝试读取文件/tmp/abc,则权限可以构造如下:
Permission perm = new java.io.FilePermission("/tmp/abc", "read");
默认的实现SecurityManager将其决定委托给java.security.AccessController实现。AccessController遍历调用堆栈,将Policy堆栈中的每个代码元素以及请求的权限(例如,FilePermission上例中的)传递给已安装的安全性。Policy根据管理员配置的权限,确定是否授予请求的访问权限。如果没有授予访问权限,则AccessController抛出java.lang.SecurityException.
下图说明了访问控制实施。在此特定示例中,调用堆栈上最初有两个元素,ClassA和 ClassB。ClassA调用中的方法 ,然后通过创建实例 ClassB尝试访问文件。构造函数创建、,如前所示,然后传递给类的 方法。在此特定情况下,只需要检查和的权限,因为模块中的所有类(包括 、和 )都会自动获得所有权限。 /tmp/abcjava.io.FileInputStreamFileInputStreamFilePermissionpermpermSecurityManagercheckPermissionClassAClassBjava.baseFileInputStreamSecurityManagerAccessController
在此示例中,ClassA和ClassB具有不同的代码特征——它们来自不同的位置并具有不同的签名者。每个可能已被授予一组不同的权限。只有表示两个类都已被授予所需的 ,AccessController才会授予对所请求文件的访问权限。 PolicyFilePermission
说明:用于 XML 处理的 Java API (JAXP)
Java API for XML Processing (JAXP) 用于使用 Java 应用程序处理 XML 数据。它支持 XML 简单 API (SAX)、文档对象模型 (DOM) 和 XML 流 API (StAX) 解析器、XML 模式验证和可扩展样式表语言转换 (XSLT)。此外,JAXP 还提供安全处理功能,可帮助保护您的应用程序和系统免受与 XML 相关的攻击。请参阅Java API for XML Processing (JAXP) 安全指南。
注:Java SE 安全编码指南包含可帮助防御 XML 相关攻击的额外建议。
Java XML 数字签名 API 是用于生成和验证 XML 签名的标准 Java API。
XML 签名可应用于任何类型的数据,XML 或二进制(请参阅XML 签名语法和处理)。生成的签名以 XML 表示。XML 签名可用于保护您的数据并提供数据完整性、消息认证和签名者认证。
该 API 旨在支持 W3C XML 签名语法和处理建议中的所有必需或推荐功能。该 API 可扩展且可插入,并且基于 Java 加密服务提供程序架构。
Java XML 数字签名 API,位于java.xml.crypto模块,由六个包组成:
以下 API 已被弃用,并将在未来版本中删除。
您可以使用此工具检查 API 依赖关系jdeprscan。请参阅Java Platform, Standard Edition Tools Reference中的jdeprscan。
以下类别已被弃用并标记为删除:
以下方法已被弃用并标记为删除:
下表描述了 Java 安全和 Kerberos 相关工具。
请参阅Java 平台标准版工具参考中的安全工具和命令。
工具 | 用法 |
---|---|
jar | 创建 Java 档案 (JAR) 文件 |
jarsigner | 对 JAR 文件进行签名和验证 |
keytool | 创建和管理密钥库 |
Windows 版 JDK 还附带了三种与 Kerberos 相关的工具。Solaris 和 Linux 操作环境自动包含同名工具,它们提供了同等功能。
工具 | 用法 |
---|---|
kinit | 获取并缓存 Kerberos 票证授予票证 |
klist | 列出本地 Kerberos 凭证缓存和密钥表中的条目 |
ktab | 管理本地 Kerberos 密钥表中存储的名称和服务密钥 |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。