Apache CXF 安全指南
使开源包含更多
红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。我们从这四个术语开始:master、slave、黑名单和白名单。由于此项工作十分艰巨,这些更改将在即将推出的几个发行版本中逐步实施。详情请查看我们的 CTO Chris Wright 信息。
第 1 章 HTTP-Compatible Bindings 的安全性
摘要
本章论述了 Apache CXF HTTP 传输支持的安全功能。这些安全功能可用于任何可以在 HTTP 传输之上进行分层的 Apache CXF 绑定。
概述
这部分论述了如何将 HTTP 传输配置为使用 SSL/TLS 安全性,其组合通常称为 HTTPS。在 Apache CXF 中,HTTPS 安全是通过在 XML 配置文件中指定设置来配置的。
如果启用 SSL/TLS 安全性,您必须确保显式禁用 SSLv3 协议,以便防止 Poodle 漏洞(CVE-2014-3566)。如需了解更多详细信息,请参阅 JBoss Fuse 6.x 和 JBoss A-MQ 6.x 中的禁用 SSLv3。
本章中会讨论以下主题:
生成 X.509 证书
使用 SSL/TLS 安全性的基本先决条件是有一个 X.509 证书集合,可识别您的服务器应用程序并选择性地识别您的客户端应用程序。您可以使用以下方法之一生成 X.509 证书:
- 使用商业第三方工具生成和管理 X.509 证书。
-
使用自由
openssl
程序(可以从 http://www.openssl.org下载)和 Java密钥存储
实用程序来生成证书(请参阅 第 2.5.3 节 “使用 CA 在 Java 密钥存储中创建签名证书”)。
HTTPS 协议强制使用 URL 完整性检查,这需要证书的身份与部署服务器的主机名匹配。详情请查看 第 2.4 节 “对 HTTPS 证书进行特殊要求”。
证书格式
在 Java 运行时,您必须以 Java 密钥存储的形式部署 X.509 证书链和可信 CA 证书。详情请查看 第 3 章 配置 HTTPS。
启用 HTTPS
在 WSDL 端点上启用 HTTPS 的先决条件是必须将端点地址指定为 HTTPS URL。有两个不同的位置来设置端点地址,且必须修改这两个位置才能使用 HTTPS URL:
WSDL 合同中指定的 HTTPS - 您必须将 WSDL 合同中的端点地址指定为带 https: 前缀的 URL,如 例 1.1 “在 WSDL 中指定 HTTPS” 所示。
例 1.1. 在 WSDL 中指定 HTTPS
<wsdl:definitions name="HelloWorld" targetNamespace="http://apache.org/hello_world_soap_http" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" ... > ... <wsdl:service name="SOAPService"> <wsdl:port binding="tns:Greeter_SOAPBinding" name="SoapPort"> <soap:address location="https://localhost:9001/SoapContext/SoapPort"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
其中
soap:address
元素的位置
属性配置为使用 HTTPS URL。对于 SOAP 以外的绑定,编辑http:address
元素的location
属性中显示的 URL。在服务器代码中指定的 HTTPS 必须通过调用
Endpoint.publish()
来确保服务器代码中发布的 URL 使用 https: 前缀来定义,如 例 1.2 “在服务器代码中指定 HTTPS” 所示。例 1.2. 在服务器代码中指定 HTTPS
// Java package demo.hw_https.server; import javax.xml.ws.Endpoint; public class Server { protected Server() throws Exception { Object implementor = new GreeterImpl(); String address = "https://localhost:9001/SoapContext/SoapPort"; Endpoint.publish(address, implementor); } ... }
没有证书的 HTTPS 客户端
例如,考虑在没有证书的安全 HTTPS 客户端的配置,如 例 1.3 “带有没有证书的 HTTPS 客户端示例” 所示。
例 1.3. 带有没有证书的 HTTPS 客户端示例
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xsi:schemaLocation="..."> <http:conduit name="{http://apache.org/hello_world_soap_http}SoapPort.http-conduit"> <http:tlsClientParameters> <sec:trustManagers> <sec:keyStore type="JKS" password="password" file="certs/truststore.jks"/> </sec:trustManagers> <sec:cipherSuitesFilter> <sec:include>.*_WITH_3DES_.*</sec:include> <sec:include>.*_WITH_DES_.*</sec:include> <sec:exclude>.*_WITH_NULL_.*</sec:exclude> <sec:exclude>.*_DH_anon_.*</sec:exclude> </sec:cipherSuitesFilter> </http:tlsClientParameters> </http:conduit> </beans>
前面的客户端配置如下所述:
TLS 安全设置在特定的 WSDL 端口上定义。在本例中,配置的 WSDL 端口有 QName {http://apache.org/hello_world_soap_http}SoapPort
。
http:tlsClientParameters
元素包含所有客户端的 TLS 配置详细信息。
sec:trustManagers
元素用于指定可信 CA 证书列表(客户端使用这个列表来决定从服务器端接收的证书)。
sec:keyStore
元素的文件属性指定 Java 密钥存储文件 truststore.jks
,其中包含一个或多个可信 CA 证书。password
属性指定访问密钥存储所需的密码 truststore.jks
。请参阅 第 3.2.2 节 “为 HTTPS 指定受信任的 CA 证书”。
您可以使用 resource
属性(在 classpath 上提供密钥存储的位置)或 url
属性来指定密钥存储的位置。特别是,
资源属性
必须与部署到 OSGi 容器中的应用程序一起使用。您必须非常小心,不要从不信任源加载信任存储。
sec:cipherSuitesFilter
元素可用于缩小客户端将要用于 TLS 连接的密码套件的选择。详情请查看 第 4 章 配置 HTTPS Cipher Suites。
带有证书的 HTTPS 客户端
考虑将 配置为具有其自身证书的安全 HTTPS 客户端。例 1.4 “使用证书的 HTTPS 客户端示例” 演示了如何配置这样的示例客户端。
例 1.4. 使用证书的 HTTPS 客户端示例
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xsi:schemaLocation="..."> <http:conduit name="{http://apache.org/hello_world_soap_http}SoapPort.http-conduit"> <http:tlsClientParameters> <sec:trustManagers> <sec:keyStore type="JKS" password="password" file="certs/truststore.jks"/> </sec:trustManagers> <sec:keyManagers keyPassword="password"> <sec:keyStore type="JKS" password="password" file="certs/wibble.jks"/> </sec:keyManagers> <sec:cipherSuitesFilter> <sec:include>.*_WITH_3DES_.*</sec:include> <sec:include>.*_WITH_DES_.*</sec:include> <sec:exclude>.*_WITH_NULL_.*</sec:exclude> <sec:exclude>.*_DH_anon_.*</sec:exclude> </sec:cipherSuitesFilter> </http:tlsClientParameters> </http:conduit> <bean id="cxf" class="org.apache.cxf.bus.CXFBusImpl"/> </beans>
前面的客户端配置如下所述:
sec:keyManagers
元素用于将 X.509 证书和私钥附加到客户端。keyPasswod
属性指定的密码用于解密证书的私钥。
sec:keyStore
元素用于指定 X.509 证书和密钥,以及 Java 密钥存储中存储的私钥。此示例声明密钥存储采用 Java 密钥存储格式(JKS)。
file
属性指定密钥存储文件的位置 wibble.jks
,其中包含客户端的 X.509 证书链和私钥。password
属性指定访问密钥存储内容所需的密钥存储密码。
预期密钥存储文件仅包含一个密钥条目,因此不需要指定密钥别名来识别该条目。但是,如果您部署使用多个密钥条目的密钥存储文件,则可以通过添加 sec:certAlias
元素作为 http:tlsClientParameters
元素的子项来指定密钥,如下所示:
<http:tlsClientParameters>
...
<sec:certAlias>CertAlias</sec:certAlias>
...
</http:tlsClientParameters>
有关如何创建密钥存储文件的详情,请参考 第 2.5.3 节 “使用 CA 在 Java 密钥存储中创建签名证书”。
您可以使用 resource
属性(在 classpath 上提供密钥存储的位置)或 url
属性来指定密钥存储的位置。特别是,
资源属性
必须与部署到 OSGi 容器中的应用程序一起使用。您必须非常小心,不要从不信任源加载信任存储。
HTTPS 服务器配置
考虑需要客户端提供 X.509 证书的安全 HTTPS 服务器。例 1.5 “HTTPS 服务器配置示例” 展示如何配置这样的服务器。
例 1.5. HTTPS 服务器配置示例
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://cxf.apache.org/configuration/security" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws" xsi:schemaLocation="..."> <httpj:engine-factory bus="cxf"> <httpj:engine port="9001"> <httpj:tlsServerParameters secureSocketProtocol="TLSv1"> <sec:keyManagers keyPassword="password"> <sec:keyStore type="JKS" password="password" file="certs/cherry.jks"/> </sec:keyManagers> <sec:trustManagers> <sec:keyStore type="JKS" password="password" file="certs/truststore.jks"/> </sec:trustManagers> <sec:cipherSuitesFilter> <sec:include>.*_WITH_3DES_.*</sec:include> <sec:include>.*_WITH_DES_.*</sec:include> <sec:exclude>.*_WITH_NULL_.*</sec:exclude> <sec:exclude>.*_DH_anon_.*</sec:exclude> </sec:cipherSuitesFilter> <sec:clientAuthentication want="true" required="true"/> </httpj:tlsServerParameters> </httpj:engine> </httpj:engine-factory> </beans>
上述服务器配置如下所述:
bus
属性引用相关的 CXF 总线实例。默认情况下,Apache CXF 运行时自动创建带有 ID cxf
的 CXF 总线实例。
在服务器端,没有 为每个 WSDL 端口配置 TLS。TLS 安全设置没有配置每个 WSDL 端口,而是应用于特定 TCP 端口,本例中为 9001
。因此,所有共享此 TCP 端口的 WSDL 端口都使用相同的 TLS 安全设置进行配置。
http:tlsServerParameters 元素包含所有服务器的 TLS 配置详情。
您必须将 secureSocketProtocol 设置为服务器端的 TLSv1
,以便防止 Poodle 漏洞(CVE-2014-3566)
sec:keyManagers
元素用于将 X.509 证书和私钥附加到服务器。keyPasswod
属性指定的密码用于解密证书的私钥。
sec:keyStore
元素用于指定 X.509 证书和密钥,以及 Java 密钥存储中存储的私钥。此示例声明密钥存储采用 Java 密钥存储格式(JKS)。
file
属性指定密钥存储文件的位置 cherry.jks
,其中包含客户端的 X.509 证书链和私钥。password
属性指定密钥存储密码,需要访问密钥存储的内容。
预期密钥存储文件仅包含一个密钥条目,因此不需要指定密钥别名来识别该条目。但是,如果您部署使用多个密钥条目的密钥存储文件,则可以通过添加 sec:certAlias
元素作为 http:tlsClientParameters
元素的子项来指定密钥,如下所示:
<http:tlsClientParameters>
...
<sec:certAlias>CertAlias</sec:certAlias>
...
</http:tlsClientParameters>
您可以使用 resource
属性或 url
属性来指定密钥存储的位置,而不是 file
属性。您必须非常小心,不要从不信任源加载信任存储。
有关如何创建此类密钥存储文件的详情,请参考 第 2.5.3 节 “使用 CA 在 Java 密钥存储中创建签名证书”。
sec:trustManagers
元素用于指定可信 CA 证书列表(服务器使用这个列表来决定客户端显示的证书)。
sec:keyStore
元素的文件属性指定 Java 密钥存储文件 truststore.jks
,其中包含一个或多个可信 CA 证书。password
属性指定访问密钥存储所需的密码 truststore.jks
。请参阅 第 3.2.2 节 “为 HTTPS 指定受信任的 CA 证书”。
您可以使用 resource
属性或 url
属性来指定密钥存储的位置,而不是 file
属性。
sec:cipherSuitesFilter
元素可用于缩小服务器将要用于 TLS 连接的密码套件的选择。详情请查看 第 4 章 配置 HTTPS Cipher Suites。
sec:clientAuthentication
元素确定服务器对客户端证书的演示位置。该元素具有以下属性:
-
需要
attribute-Iftrue
(默认),服务器在 TLS 握手过程中请求客户端显示 X.509 证书;如果为false
,服务器 不会 请求客户端显示 X.509 证书。 -
必需的
属性为true
,如果客户端在 TLS 握手过程中无法显示 X.509 证书,服务器会引发异常;如果为false
(默认值),服务器 不会 引发异常,如果客户端无法显示 X.509 证书,则服务器不会引发异常。
第 2 章 管理证书
摘要
TLS 身份验证使用 X.509 证书,它是验证应用程序对象的通用安全可靠的方法。您可以创建 X.509 证书来识别您的红帽 Fuse 应用程序。
2.1. 什么是 X.509 证书?
证书的角色
公钥的完整性
安全应用程序的身份验证取决于应用程序的证书中的公钥值的完整性。如果 impostor 将公钥替换为其自己的公钥,它可以模拟真正的应用并获得安全数据的访问权限。
要防止这种攻击,所有证书必须由 证书颁发机构 (CA)签名。CA 是一个可信节点,用于确认证书中的公钥值的完整性。
数字签名
CA 通过在证书中添加 数字签名 来签署证书。数字签名是一个使用 CA 私钥编码的消息。通过为 CA 分发证书,为应用程序提供 CA 的公钥。应用程序通过用 CA 的公钥解码 CA 的数字签名来验证证书是否有效。
提供的演示证书是自签名证书。这些证书不安全,因为任何人都可以访问其私钥。要保护您的系统,必须创建由可信 CA 签名的新证书。
X.509 证书的内容
X.509 证书包含有关证书主体和证书签发者(签发证书的 CA)的信息。证书以 Abstract syntax Notation One(ASN.1)形式编码,这是描述可以在网络上发送或接收的消息的标准语法。
证书的角色是将身份与公钥值相关联。更多详情,证书包括:
- 标识证书所有者的 主体可分辨名称(DN)。
- 与主题关联的 公钥。
- X.509 版本信息。
- 唯一标识证书 的序列号。
- 标识发布证书的 CA 的 签发者 DN。
- 签发者的数字签名。
- 用于为证书签名的算法相关的信息。
- 一些可选的 X.509 v.3 扩展 ; 例如,存在可区分 CA 证书和端点证书的扩展。
可识别的名称
DN 是一个通用目的 X.500 标识符,通常在安全上下文中使用。
有关 DN 的详情,请参阅 附录 A, ASN.1 和可辨识名称。
2.2. 认证授权机构
2.2.1. 证书颁发机构简介
CA 由一组用来创建和管理证书的工具以及包含所有生成的证书的数据库组成。在设置系统时,务必要选择足够安全的 CA。
您可以使用两种 CA 类型:
2.2.2. 商业认证机构
签名证书
有几种商业 CA 可用。使用商用 CA 签署证书的机制取决于您选择哪个 CA。
商业 CA 的优点
商业 CA 的一个优点是它们通常被大量人信任。如果您的应用程序被设计为可用于您的机构外部的系统,请使用商业 CA 为证书签名。如果您的应用程序在内部网络中使用,则可能存在私有 CA。
选择 CA 的条件
在选择商用 CA 之前,请考虑以下标准:
- 商业 CA 的证书签名请求是什么?
- 您的应用程序是否仅在内部网络上可用?
- 与订阅商业 CA 的成本相比,设置私有 CA 的潜在成本是什么?
2.2.3. 私有证书颁发机构
选择 CA 软件包
如果要负责为您的系统签名证书,请设置私有 CA。要设置私有 CA,您需要访问提供创建和签名证书的实用程序的软件包。有以下几种软件包可用。
openssl 软件包
一个可让您设置私有 CA 的软件包是 OpenSSL http://www.openssl.org。OpenSSL 软件包包含用于生成和签名证书的基本命令行工具。OpenSSL 命令行工具的完整文档位于 http://www.openssl.org/docs。
使用 OpenSSL 设置私有 CA
要设置私有 CA,请查看 第 2.5 节 “创建您自己的证书” 中的说明。
为私有证书颁发机构选择主机
选择主机是设置私有 CA 的一个重要步骤。与 CA 主机关联的安全级别决定了与 CA 签名的证书关联的信任级别。
如果您要设置用于 Red Hat Fuse 应用程序的开发和测试的 CA,请使用应用程序开发人员可访问的任何主机。但是,当您创建 CA 证书和私钥时,不要在运行安全关键应用程序的任何主机上使用 CA 私钥。
安全预防措施
如果您要设置 CA 为您要部署的应用程序签名的证书,使 CA 主机尽可能安全。例如,采取以下预防措施来保护您的 CA:
- 不要将 CA 连接到网络。
- 将 CA 的所有访问权限限制为有限一组可信用户。
- 使用 RF-shield 防止 CA 不受无线电音。
2.3. 证书链
证书链
图 2.1 “Depth 2 的证书链” 展示了简单证书链的示例。
图 2.1. Depth 2 的证书链
自签名证书
信任链
证书链的目的是建立从对等证书到可信 CA 证书的信任链。通过签名在对等证书中的身份的 CA vouches。如果 CA 是您信任的一个(由 root 证书目录中存在 CA 证书的副本),这意味着您可以信任签名的对等证书。
由多个 CA 签名的证书
CA 证书可由其他 CA 签名。例如,应用程序证书可由 Progress Software 财务部门的 CA 签名,后者由自签名商业 CA 签名。
图 2.2 “低于 3 的证书链” 显示此证书链的内容:
图 2.2. 低于 3 的证书链
可信 CA
2.4. 对 HTTPS 证书进行特殊要求
概述
HTTPS 规范要求 HTTPS 客户端能够验证服务器的身份。这可能会影响您生成 X.509 证书的方式。验证服务器身份的机制取决于客户端的类型。有些客户端只能接受由特定可信 CA 签名的服务器证书来验证服务器身份。另外,客户端也可以检查服务器证书的内容,并只接受满足特定限制的证书。
如果没有特定于应用的机制,HTTPS 规范会定义一个通用机制,称为 HTTPS URL 完整性检查,用于验证服务器身份。这是 Web 浏览器使用的标准机制。
HTTPS URL 完整性检查
URL 完整性检查的基本概念是服务器证书的身份必须与服务器主机名匹配。此完整性检查对 HTTPS 生成 X.509 证书具有重要影响: 证书身份(通常是证书主体 DN 的通用名称)必须与部署 HTTPS 服务器的主机名匹配。
URL 完整性检查旨在防止 中间人攻击。
参考
HTTPS URL 完整性检查由 RFC 2818 指定,由互联网工程任务组(IETF)发布。http://www.ietf.org/rfc/rfc2818.txt
如何指定证书身份
URL 完整性检查中使用的证书身份可使用以下之一指定:
使用 commonName
指定证书身份(用于 URL 完整性检查的目的)的常见方式是通过证书的 subject DN 中的通用名称(CN)。
例如,如果服务器支持通过以下 URL 保护 TLS 连接:
https://www.redhat.com/secure
对应的服务器证书会有以下主题 DN:
C=IE,ST=Co. Dublin,L=Dublin,O=RedHat, OU=System,CN=www.redhat.com
其中 CN 已设为主机名 www.redhat.com
。
有关如何在新证书中设置主体 DN 的详情,请参考 第 2.5 节 “创建您自己的证书”。
使用 subjectAltName(多主机)
将主题 DN 的通用名称用于证书身份,具有 一次只能 指定一个主机名的缺点。但是,如果在多设备主机上部署证书,您可能会发现,允许证书 与任何 多设备主机名一起使用。在这种情况下,需要定义一个带有多个替代身份的证书,这只能使用 subjectAltName
证书扩展名。
例如,如果您有一个支持连接到以下主机名之一的多home主机:
www.redhat.com www.jboss.org
然后您可以定义一个可明确列出这些 DNS 主机名的 subjectAltName
。如果您使用 openssl
程序生成证书,请编辑 openssl.cnf
配置文件的相关行来指定 subjectAltName
扩展的值,如下所示:
subjectAltName=DNS:www.redhat.com,DNS:www.jboss.org
其中 HTTPS 协议与在 subjectAltName
中列出的 DNS 主机名之一( subjectAltName
的优先级高于通用名称)匹配服务器主机名。
HTTPS 协议也支持主机名中的通配符字符 \*
。例如,您可以定义 subjectAltName
,如下所示:
subjectAltName=DNS:*.jboss.org
此证书身份与域 jboss.org 中的任意三组件主机名匹配。
您不得 在域名中 使用通配符字符(并且您必须小心小心,不要通过忘记在域名前面键入点来意外这样做 。。
、分隔符)。例如,如果您指定了 *jboss.org
,您的证书可用于*任何*域,该域以字母 jboss
结束。
2.5. 创建您自己的证书
2.5.1. 先决条件
openssl 工具程序
本节中描述的步骤基于 OpenSSL 项目中的 OpenSSL 命令行工具。有关 OpenSSL 命令行工具的其他文档,请参阅 http://www.openssl.org/docs/。
CA 目录结构示例
为了说明这一点,假设 CA 数据库具有以下目录结构:
|
|
|
|
其中 X509CA 是 CA 数据库的父目录。
2.5.2. 设置您的 Own CA
要执行的子步骤
这部分论述了如何设置您自己的私有 CA。在为实际部署设置 CA 之前,请阅读 第 2.2.3 节 “私有证书颁发机构” 中的其他注释。
要设置您自己的 CA,请执行以下步骤:
在您的 PATH 中添加 bin 目录
在安全 CA 主机上,将 OpenSSL bin
目录添加到您的路径中:
Windows
> set PATH=OpenSSLDir\bin;%PATH%
UNIX
% PATH=OpenSSLDir/bin:$PATH; export PATH
此步骤使 openssl
实用程序可从命令行使用。
创建 CA 目录树
创建新目录 X509CA,以容纳新 CA。该目录用于保存与 CA 关联的所有文件。在 X509CA 目录下,创建以下目录层次结构:
|
|
|
|
复制并编辑 openssl.cnf 文件
将 OpenSSL 安装中的 openssl.cnf
示例复制到 X509CA 目录。
编辑 openssl.cnf
以反映 X509CA 目录的目录结构,并识别新 CA 使用的文件。
编辑 openssl.cnf
文件的 [CA_default]
部分,使其类似如下:
#############################################################
[ CA_default ]
dir = X509CA # Where CA files are kept
certs = $dir/certs # Where issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # Database index file
new_certs_dir = $dir/newcerts # Default place for new certs
certificate = $dir/ca/new_ca.pem # The CA certificate
serial = $dir/serial # The current serial number
crl = $dir/crl.pem # The current CRL
private_key = $dir/ca/new_ca_pk.pem # The private key
RANDFILE = $dir/ca/.rand
# Private random number file
x509_extensions = usr_cert # The extensions to add to the cert
...
此时您可以决定编辑 OpenSSL 配置的其他详情,请参阅 http://www.openssl.org/docs/。
初始化 CA 数据库
在 X509CA 目录中,初始化两个文件,串行
和 index.txt
。
Windows
要在 Windows 中初始化 串行
文件,请输入以下命令:
> echo 01 > serial
要创建空文件 index.txt
,在 Windows 的 X509CA 目录中从命令行启动 Windows Notepad,如下所示:
> notepad index.txt
为了响应带有文本的对话框,Cannot find text.txt 文件。您要创建新文件?
,点击 是,并关闭 Notepad。
UNIX
要在 UNIX 中初始化 串行
文件和 index.txt
文件,请输入以下命令:
% echo "01" > serial % touch index.txt
CA 使用这些文件来维护其证书文件数据库。
index.txt
文件最初必须完全为空,甚至不能包含空格。
创建自签名 CA 证书和私钥
openssl req -x509 -new -config X509CA/openssl.cnf -days 365 -out X509CA/ca/new_ca.pem -keyout X509CA/ca/new_ca_pk.pem
该命令提示您输入 CA 私钥的密码短语和 CA 可区分名称的详情。例如:
Using configuration from X509CA/openssl.cnf
Generating a 512 bit RSA private key
....++
.++
writing new private key to 'new_ca_pk.pem'
Enter PEM pass phrase:
Verifying password - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be
incorporated into your certificate request.
What you are about to enter is what is called a Distinguished
Name or a DN. There are quite a few fields but you can leave
some blank. For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) []:IE
State or Province Name (full name) []:Co. Dublin
Locality Name (eg, city) []:Dublin
Organization Name (eg, company) []:Red Hat
Organizational Unit Name (eg, section) []:Finance
Common Name (eg, YOUR name) []:Gordon Brown
Email Address []:gbrown@redhat.com
CA 的安全性取决于私钥文件的安全性以及此步骤中使用的私钥密码短语。
您必须确保 CA 证书和私钥、new_ca.pem
和 new_ca_pk.pem
的文件名和位置与 openssl.cnf
中指定的值相同(请参阅前面的步骤)。
您现在已准备好使用您的 CA 签署证书。
2.5.3. 使用 CA 在 Java 密钥存储中创建签名证书
要执行的子步骤
要在 Java 密钥存储(JKS)中创建并签署证书,CertName.jks
可执行以下子步骤:
将 Java bin 目录添加到您的 PATH 中
如果您还没有这样做,请在路径中添加 Java bin
目录:
Windows
> set PATH=JAVA_HOME\bin;%PATH%
UNIX
% PATH=JAVA_HOME/bin:$PATH; export PATH
此步骤使 keytool
程序从命令行可用。
生成证书和私钥对
打开命令提示符,并将目录更改到存储密钥存储文件 KeystoreDir 的目录。使用以下命令:
keytool -genkey -dname "CN=Alice, OU=Engineering, O=Progress, ST=Co. Dublin, C=IE" -validity 365 -alias CertAlias -keypass CertPassword -keystore CertName.jks -storepass CertPassword
这个 keytool
命令通过 -genkey
选项调用,生成 X.509 证书和一个匹配的私钥。证书和密钥都放在新创建的密钥存储 CertName.jks
中的密钥条目中。由于指定的密钥存储( CertName.jks
)在发出 命令之前不存在,因此 keytool
隐式创建新的密钥存储。
-dname
和 -validity
标志定义新创建的 X.509 证书的内容,分别指定主题 DN 和之前的天数。有关 DN 格式的详情,请参考 附录 A, ASN.1 和可辨识名称。
subject DN 的某些部分必须与 CA 证书中的值匹配(在 openssl.cnf
文件的 CA Policy 部分中指定)。默认的 openssl.cnf
文件需要以下条目匹配:
- 国家/地区名称(C)
- 州或省名称(ST)
- 机构名称(O)
如果您没有观察限制,OpenSSL CA 将拒绝为证书签名(请参阅 “为 CSR 签名”一节 )。
创建证书签名请求
为 CertName.jks
证书创建新证书签名请求(CSR),如下所示:
keytool -certreq -alias CertAlias -file CertName_csr.pem -keypass CertPassword -keystore CertName.jks -storepass CertPassword
此命令将 CSR 导出至文件 CertName_csr.pem
。
为 CSR 签名
openssl ca -config X509CA/openssl.cnf -days 365 -in CertName_csr.pem -out CertName.pem
要成功为证书签名,您必须输入 CA 私钥密码短语(请参阅 第 2.5.2 节 “设置您的 Own CA”)。
如果要使用默认 CA 以外的 CA 证书对 CSR 签名,请使用 -cert
和 -keyfile
选项分别指定 CA 证书及其私钥文件。
转换为 PEM 格式
将签名证书 CertName.pem
转换为 PEM 只格式,如下所示:
openssl x509 -in CertName.pem -out CertName.pem -outform PEM
连接文件
连接 CA 证书文件和 CertName.pem
证书文件,如下所示:
Windows
copy CertName.pem + X509CA\ca\new_ca.pem CertName.chain
UNIX
cat CertName.pem X509CA/ca/new_ca.pem> CertName.chain
使用完整证书链更新密钥存储
通过导入证书的完整证书链,更新密钥存储 . CertName.jks
,如下所示:
keytool -import -file CertName.chain -keypass CertPassword -keystore CertName.jks -storepass CertPassword
根据需要重复步骤
重复步骤 2 到 7,为您的系统创建完整的证书集合。
2.5.4. 使用 CA 创建 Signed PKCS#12 Certificates
要执行的子步骤
如果您设置了私有 CA,如 第 2.5.2 节 “设置您的 Own CA” 所述,您现在已准备好创建并签名您自己的证书。
要创建并签名 PKCS#12 格式 CertName.p12
的证书,请执行以下子步骤:
在您的 PATH 中添加 bin 目录
如果您还没有这样做,请在路径中添加 OpenSSL bin
目录,如下所示:
Windows
> set PATH=OpenSSLDir\bin;%PATH%
UNIX
% PATH=OpenSSLDir/bin:$PATH; export PATH
此步骤使 openssl
实用程序可从命令行使用。
配置 subjectAltName 扩展(可选)
执行这一步,如果您为客户端强制执行 URL 完整性检查的 HTTPS 服务器,并且计划在多设备主机上部署服务器,或者带有几个 DNS 名称别名(例如,如果您在多主 Web 服务器上部署证书)的 HTTPS 服务器,请执行这个步骤。在这种情况下,证书身份必须与多个主机名匹配,这只能通过添加 subjectAltName
证书扩展名来实现(请参阅 第 2.4 节 “对 HTTPS 证书进行特殊要求”)。
要配置 subjectAltName
扩展,请编辑 CA 的 openssl.cnf
文件,如下所示:
将以下
req_extensions
设置添加到[req]
部分(如果openssl.cnf
文件中不存在):# openssl Configuration File ... [req] req_extensions=v3_req
添加
[v3_req]
部分标题(如果openssl.cnf
文件中不存在)。在[v3_req]
部分,添加或修改subjectAltName
设置,并将其设置为 DNS 主机名列表。例如,如果服务器主机支持替代 DNS 名称www.redhat.com
和jboss.org
,请按如下所示设置subjectAltName
:# openssl Configuration File ... [v3_req] subjectAltName=DNS:www.redhat.com,DNS:jboss.org
在适当的 CA 配置部分添加
copy_extensions
设置。用于签名证书的 CA 配置部分是以下之一:-
由
openssl ca
命令的-name
选项指定的部分, 在
[ca]
部分下指定default_ca
设置的部分(通常为[CA_default]
)。例如,如果适当的 CA 配置部分为
[CA_default]
,请设置copy_extensions
属性,如下所示:# openssl Configuration File ... [CA_default] copy_extensions=copy
此设置确保证书签名请求中存在的证书扩展被复制到签名证书中。
-
由
创建证书签名请求
为 CertName.p12
证书创建新证书签名请求(CSR),如下所示:
openssl req -new -config X509CA/openssl.cnf -days 365 -out X509CA/certs/CertName_csr.pem -keyout X509CA/certs/CertName_pk.pem
这个命令提示您输入证书的私钥的密码短语,以及证书可识别名称的信息。
CSR 可识别名称中的一些条目必须与 CA 证书中的值匹配(在 openssl.cnf
文件的 CA Policy 部分中指定)。默认的 openssl.cnf
文件要求以下条目匹配:
- 国家/地区名称
- 州或省名称
- 机构名称
证书主题 DN 的 Common Name 是通常用于代表证书所有者的身份的字段。通用名称必须符合以下条件:
- 对于 OpenSSL 证书颁发机构生成的每个证书,通用名称必须 不同。
- 如果您的 HTTPS 客户端实现了 URL 完整性检查,您必须确保 Common Name 与要部署的证书的 DNS 名称相同(请参阅 第 2.4 节 “对 HTTPS 证书进行特殊要求”)。
对于 HTTPS URL 完整性检查的目的,subjectAltName
扩展优先于 Common Name。
Using configuration from X509CA/openssl.cnf Generating a 512 bit RSA private key .++ .++ writing new private key to 'X509CA/certs/CertName_pk.pem' Enter PEM pass phrase: Verifying password - Enter PEM pass phrase: ----- You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank. For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) []:IE State or Province Name (full name) []:Co. Dublin Locality Name (eg, city) []:Dublin Organization Name (eg, company) []:Red Hat Organizational Unit Name (eg, section) []:Systems Common Name (eg, YOUR name) []:Artix Email Address []:info@redhat.com Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []:password An optional company name []:Red Hat
为 CSR 签名
openssl ca -config X509CA/openssl.cnf -days 365 -in X509CA/certs/CertName_csr.pem -out X509CA/certs/CertName.pem
此命令需要与 new_ca.pem
CA 证书关联的私钥的密码短语。例如:
Using configuration from X509CA/openssl.cnf Enter PEM pass phrase: Check that the request matches the signature Signature ok The Subjects Distinguished Name is as follows countryName :PRINTABLE:'IE' stateOrProvinceName :PRINTABLE:'Co. Dublin' localityName :PRINTABLE:'Dublin' organizationName :PRINTABLE:'Red Hat' organizationalUnitName:PRINTABLE:'Systems' commonName :PRINTABLE:'Bank Server Certificate' emailAddress :IA5STRING:'info@redhat.com' Certificate is to be certified until May 24 13:06:57 2000 GMT (365 days) Sign the certificate? [y/n]:y 1 out of 1 certificate requests certified, commit? [y/n]y Write out database with 1 new entries Data Base Updated
要成功为证书签名,您必须输入 CA 私钥密码短语(请参阅 第 2.5.2 节 “设置您的 Own CA”)。
如果您没有在 openssl.cnf
文件的 [CA_default]
部分下设置 copy_extensions=copy
,则签名证书不会包括原始 CSR 中的任何证书扩展。
连接文件
连接 CA 证书文件、CertName.pem
证书文件和 CertName_pk.pem
私钥文件,如下所示:
Windows
copy X509CA\ca\new_ca.pem + X509CA\certspass:quotes[_CertName_].pem + X509CA\certspass:quotes[_CertName_]_pk.pem X509CA\certspass:quotes[_CertName_]_list.pem
UNIX
cat X509CA/ca/new_ca.pem X509CA/certs/CertName.pem X509CA/certs/CertName_pk.pem > X509CA/certs/CertName_list.pem
创建 PKCS#12 文件
从 CertName_list.pem
文件中创建一个 PKCS#12 文件,如下所示:
openssl pkcs12 -export -in X509CA/certs/CertName_list.pem -out X509CA/certs/CertName.p12 -name "New cert"
系统会提示您输入一个密码来加密 PKCS#12 证书。此密码通常与 CSR 密码相同(许多证书存储库需要)。
根据需要重复步骤
重复步骤 3 到 6,为您的系统创建完整的证书集合。
(可选)清除 subjectAltName 扩展
为特定主机机器生成证书后,建议清除 openssl.cnf
文件中的 subjectAltName
设置,以避免意外将错误 DNS 名称分配给另一组证书。
在 openssl.cnf
文件中,注释掉 subjectAltName
设置(在行首添加一个 #
字符),并注释掉 copy_extensions
设置。
第 3 章 配置 HTTPS
摘要
本章论述了如何配置 HTTPS 端点。
3.1. 验证方案
3.1.1. target-Only Authentication
概述
当为只为目标验证配置了应用程序时,目标会将自己验证给客户端,但客户端并不对目标对象进行身份验证,如 图 3.1 “只适用于目标身份验证” 所示。
图 3.1. 只适用于目标身份验证
安全握手
在运行应用程序前,客户端和服务器应设置为如下:
- 证书链与服务器相关联。证书链以 Java 密钥存储的形式提供(ee 第 3.3 节 “指定应用程序的 Own 证书”)。
- 客户端提供了一个或多个可信证书颁发机构(CA)列表。(请参阅 第 3.2 节 “指定受信任的 CA 证书”)。
在安全握手期间,服务器会将其证书链发送到客户端(请参阅 图 3.1 “只适用于目标身份验证”)。然后,客户端会搜索其可信 CA 列表以查找与服务器证书链中之一的 CA 证书匹配的 CA 证书。
HTTPS 示例
在客户端中,只验证目标不需要策略设置。只需在不将 X.509 证书与 HTTPS 端口关联 的情况下,配置您的客户端。您必须为客户端提供可信 CA 证书列表(请参阅 第 3.2 节 “指定受信任的 CA 证书”)。
在服务器端,在服务器的 XML 配置文件中,确保 sec:clientAuthentication
元素不需要客户端身份验证。可以省略此元素,在这种情况下,默认策略 不需要 客户端身份验证。但是,如果存在 sec:clientAuthentication
元素,则应按照以下方式进行配置:
<http:destination id="{Namespace}PortName.http-destination"> <http:tlsServerParameters secureSocketProtocol="TLSv1"> ... <sec:clientAuthentication want="false" required="false"/> </http:tlsServerParameters> </http:destination>
您必须将 secureSocketProtocol 设置为服务器端的 TLSv1
,以便防止 Poodle 漏洞(CVE-2014-3566)
如果 want 属性设为 false(默认值),指定服务器不会在 TLS 握手期间从客户端请求 X.509 证书。required 属性也被设置为 false(默认值),指定没有客户端证书在 TLS 握手期间不会触发异常。
want
属性可以设为 true
或设置为 false
。如果设置为 true
,则 希望
设置会导致服务器在 TLS 握手过程中请求客户端证书,但对缺少证书的客户端没有引发异常,只要将所需的属性设置为 false
。
另外,还需要将 X.509 证书与服务器的 HTTPS 端口(请参阅 第 3.3 节 “指定应用程序的 Own 证书” )关联,并为服务器提供可信 CA 证书列表(请参阅 第 3.2 节 “指定受信任的 CA 证书”。
密码套件的选择可能会影响是否支持仅限目标验证(请参阅 第 4 章 配置 HTTPS Cipher Suites)。
3.1.2. 双向身份验证
概述
当为相互验证配置了应用程序时,目标会将自己验证给客户端,客户端则向目标验证自己。图 3.2 “双向身份验证” 中演示了这种情况。在这种情况下,服务器和客户端都需要一个 X.509 证书才能获得安全性。
图 3.2. 双向身份验证
安全握手
在运行应用程序前,客户端和服务器必须设置如下:
- 客户端和服务器都有关联的证书链(请参阅 第 3.3 节 “指定应用程序的 Own 证书”)。
- 客户端和服务器均配置了可信证书颁发机构(CA)列表(请参阅 第 3.2 节 “指定受信任的 CA 证书”)。
在 TLS 握手期间,服务器会将其证书链发送到客户端,并且客户端将其证书链发送到服务器 - 请参阅 图 3.1 “只适用于目标身份验证”。
HTTPS 示例
在客户端中,没有相互身份验证所需的策略设置。只需将 X.509 证书与客户端的 HTTPS 端口关联(请参阅 第 3.3 节 “指定应用程序的 Own 证书”)。您还需要为客户端提供可信 CA 证书列表(请参阅 第 3.2 节 “指定受信任的 CA 证书”)。
在服务器端,在服务器的 XML 配置文件中,确保将 sec:clientAuthentication
元素配置为 需要 客户端身份验证。例如:
<http:destination id="{Namespace}PortName.http-destination"> <http:tlsServerParameters secureSocketProtocol="TLSv1"> ... <sec:clientAuthentication want="true" required="true"/> </http:tlsServerParameters> </http:destination>
您必须将 secureSocketProtocol 设置为服务器端的 TLSv1
,以便防止 Poodle 漏洞(CVE-2014-3566)
如果 want
属性设为 true
,指定服务器在 TLS 握手期间从客户端请求 X.509 证书。必需
属性也设为 true
,指定没有客户端证书在 TLS 握手期间触发异常。
另外,还需要将 X.509 证书与服务器的 HTTPS 端口(请参阅 第 3.3 节 “指定应用程序的 Own 证书”)关联,并为服务器提供可信 CA 证书列表(请参阅 第 3.2 节 “指定受信任的 CA 证书”。
密码套件的选择可能会影响是否支持相互验证(请参阅 第 4 章 配置 HTTPS Cipher Suites)。
3.2. 指定受信任的 CA 证书
3.2.1. 部署可信 CA 证书的时间
概述
当应用程序在 SSL/TLS 握手过程中收到 X.509 证书时,应用程序会通过检查签发者 CA 是否是预定义的 CA 证书之一,决定是否信任接收的证书。如果收到的 X.509 证书有效由应用程序信任的 CA 证书有效签名,则证书被视为可信性;否则,它将被拒绝。
哪个应用程序需要指定可信 CA 证书?
作为 HTTPS 握手的一部分,任何可能会接收 X.509 证书的应用程序都必须指定可信 CA 证书列表。例如,这包括以下类型的应用程序:
- 所有 HTTPS 客户端。
- 任何支持 相互身份验证的 HTTPS 服务器。
3.2.2. 为 HTTPS 指定受信任的 CA 证书
CA 证书格式
CA 证书必须采用 Java 密钥存储格式提供。
Apache CXF 配置文件中的 CA 证书部署
要为 HTTPS 传输部署一个或多个可信根 CA,请执行以下步骤:
-
汇编您要部署的可信 CA 证书的集合。可信 CA 证书可从公共 CA 或私有 CA 获取(有关如何生成您自己的 CA 证书的详情,请参考 第 2.5 节 “创建您自己的证书”)。可信 CA 证书可以采用任何与 Java
密钥存储
实用程序兼容的格式;例如 PEM 格式。所有这些都是证书本身--不需要私钥和密码。 给定 CA 证书
cacert.pem
以 PEM 格式,您可以通过输入以下命令将证书添加到 JKS 信任存储(或创建新的信任存储):keytool -import -file cacert.pem -alias CAAlias -keystore truststore.jks -storepass StorePass
其中 CAAlias 是一个方便的标签,可让您使用
keytool
程序访问这个特定 CA 证书。filetruststore.jks
是包含 CA 证书的密钥存储文件,如果此文件尚不存在,则keytool
程序会创建一个。StorePass 密码提供对密钥存储文件truststore.jks
的访问。-
根据需要重复第 2 步,将所有 CA 证书添加到 truststore 文件
truststore.jks
中。 编辑相关的 XML 配置文件以指定信任存储文件的位置。您必须在相关 HTTPS 端口配置中包含
sec:trustManagers
元素。例如,您可以配置客户端端口,如下所示:
<!-- Client port configuration --> <http:conduit id="{Namespace}PortName.http-conduit"> <http:tlsClientParameters> ... <sec:trustManagers> <sec:keyStore type="JKS" password="StorePass" file="certs/truststore.jks"/> </sec:trustManagers> ... </http:tlsClientParameters> </http:conduit>
其中
type
属性指定 truststore 使用 JKS 密钥存储实施,而 StorePass 是访问truststore.jks
密钥存储所需要的密码。配置服务器端口,如下所示:
<!-- Server port configuration --> <http:destination id="{Namespace}PortName.http-destination"> <http:tlsServerParameters secureSocketProtocol="TLSv1"> ... <sec:trustManagers> <sec:keyStore type="JKS" password="StorePass" file="certs/truststore.jks"/> </sec:trustManagers> ... </http:tlsServerParameters> </http:destination>
重要您必须将 secureSocketProtocol 设置为服务器端的
TLSv1
,以便防止 Poodle 漏洞(CVE-2014-3566)警告包含信任存储的目录(例如,X509Deploy
/truststores/
)应是一个安全目录(只能由管理员写入)。
3.3. 指定应用程序的 Own 证书
3.3.1. 为 HTTPS 部署 Own 证书
概述
使用 HTTPS 传输时使用 XML 配置文件部署应用程序的证书。
流程
要为 HTTPS 传输部署应用程序自己的证书,请执行以下步骤:
获取 Java 密钥存储格式 CertName
.jks
的应用程序证书。有关如何以 Java 密钥存储格式创建证书的说明,请参阅 第 2.5.3 节 “使用 CA 在 Java 密钥存储中创建签名证书”。注意一些 HTTPS 客户端(例如,Web 浏览器)执行 URL 完整性检查,这需要证书的身份与部署服务器的主机名匹配。详情请查看 第 2.4 节 “对 HTTPS 证书进行特殊要求”。
将证书的密钥存储 CertName
.jks
复制到部署主机上的证书目录中;例如,X509Deploy/certs
。证书目录应该是只能由管理员和其它特权用户写入的安全目录。
编辑相关的 XML 配置文件,以指定证书密钥存储 CertName
.jks
的位置。您必须在相关 HTTPS 端口配置中包含sec:keyManagers
元素。例如,您可以配置客户端端口,如下所示:
<http:conduit id="{Namespace}PortName.http-conduit"> <http:tlsClientParameters> ... <sec:keyManagers keyPassword="CertPassword"> <sec:keyStore type="JKS" password="KeystorePassword" file="certs/CertName.jks"/> </sec:keyManagers> ... </http:tlsClientParameters> </http:conduit>
其中
keyPassword
属性指定解密证书私钥(即 CertPassword)所需的密码,即type
属性指定信任存储使用 JKS 密钥存储实施,password
属性指定访问 CertName.jks
密钥存储(即 KeystorePassword)所需的密码。配置服务器端口,如下所示:
<http:destination id="{Namespace}PortName.http-destination"> <http:tlsServerParameters secureSocketProtocol="TLSv1"> ... <sec:keyManagers keyPassword="CertPassword"> <sec:keyStore type="JKS" password="KeystorePassword" file="certs/CertName.jks"/> </sec:keyManagers> ... </http:tlsServerParameters> </http:destination>
重要您必须将 secureSocketProtocol 设置为服务器端的
TLSv1
,以便防止 Poodle 漏洞(CVE-2014-3566)警告包含应用程序证书的目录(例如,X509Deploy
/certs/
)应为安全目录(即,只能由管理员读取和可写入)。警告包含 XML 配置文件的目录应该是一个安全目录(即,只能由管理员读取和可写入),因为配置文件以纯文本中包含密码。
第 4 章 配置 HTTPS Cipher Suites
摘要
本章介绍了如何指定客户端和服务器可用的密码套件列表,以建立 HTTPS 连接。在安全握手期间,客户端选择与服务器可用的其中一个密码套件匹配的加密套件。
4.1. 支持的 Cipher Suites
概述
密码套件 是安全算法的集合,它决定了如何实施 SSL/TLS 连接。
例如,SSL/TLS 协议要求使用消息摘要算法签名的消息。但是,选择摘要算法由用于连接的特定密码套件决定。通常,应用程序可选择 MD5 或 SHA 摘要算法。
Apache CXF 中可用于 SSL/TLS 安全性的密码套件取决于端点上指定的 JSSE 供应商。
JCE/JSSE 和安全供应商
Java Cryptography Extenss(JCE)和 Java 安全套接字扩展(JSSE)组成了一个可插拔框架,允许您将 Java 安全实施替换为任意第三方工具包(称为 安全供应商 )。
SunJSSE 供应商
在实践中,只有 SUN 的 JSSE 提供商名为 SunJSSE
,对 Apache CXF 的安全功能进行了测试。
因此,Apache CXF 中的 SSL/TLS 实现和 Apache CXF 中的可用密码套件列表有效由 SUN 的 JSSE 供应商中提供的。
SunJSSE 支持的密码套件
J2SE 1.5.0 Java 开发套件中的 SUN 的 JSSE 供应商支持以下密码套件(请参阅 SUN 的 JSSE 参考指南 的附录 A ):
标准密码:
SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA SSL_DHE_DSS_WITH_DES_CBC_SHA SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA SSL_DHE_RSA_WITH_DES_CBC_SHA SSL_RSA_EXPORT_WITH_DES40_CBC_SHA SSL_RSA_EXPORT_WITH_RC4_40_MD5 SSL_RSA_WITH_3DES_EDE_CBC_SHA SSL_RSA_WITH_DES_CBC_SHA SSL_RSA_WITH_RC4_128_MD5 SSL_RSA_WITH_RC4_128_SHA TLS_DHE_DSS_WITH_AES_128_CBC_SHA TLS_DHE_DSS_WITH_AES_256_CBC_SHA TLS_DHE_RSA_WITH_AES_128_CBC_SHA TLS_DHE_RSA_WITH_AES_256_CBC_SHA TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA TLS_KRB5_EXPORT_WITH_RC4_40_MD5 TLS_KRB5_EXPORT_WITH_RC4_40_SHA TLS_KRB5_WITH_3DES_EDE_CBC_MD5 TLS_KRB5_WITH_3DES_EDE_CBC_SHA TLS_KRB5_WITH_DES_CBC_MD5 TLS_KRB5_WITH_DES_CBC_SHA TLS_KRB5_WITH_RC4_128_MD5 TLS_KRB5_WITH_RC4_128_SHA TLS_RSA_WITH_AES_128_CBC_SHA TLS_RSA_WITH_AES_256_CBC_SHA
null 加密,仅限完整性的密码:
SSL_RSA_WITH_NULL_MD5 SSL_RSA_WITH_NULL_SHA
匿名 Diffie-Hellman 密码(无身份验证):
SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 SSL_DH_anon_WITH_3DES_EDE_CBC_SHA SSL_DH_anon_WITH_DES_CBC_SHA SSL_DH_anon_WITH_RC4_128_MD5 TLS_DH_anon_WITH_AES_128_CBC_SHA TLS_DH_anon_WITH_AES_256_CBC_SHA
JSSE 参考指南
有关 SUN 的 JSSE 框架的更多信息,请参阅 JSSE 参考指南,访问以下位置:
http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html
4.2. 密码套件过滤器
概述
在典型的应用程序中,您通常希望将可用密码套件列表限制为 JSSE 供应商支持的密码子集。
通常,您应该使用 sec:cipherSuitesFilter
元素而不是 sec:cipherSuites
元素来选择要使用的密码套件。
不建议使用 sec:cipherSuites
元素,因为它具有非直观的语义:您可以使用它来要求加载的安全供应商至少支持列出的密码套件。但是,加载的安全供应商可能会支持比指定的更多的密码套件。因此,当您使用 sec:cipherSuites
元素时,它并不清楚在运行时支持哪些密码套件。
命名空间
表 4.1 “用于配置 Cipher Suite Filters 的命名空间” 显示本节中引用的 XML 命名空间:
表 4.1. 用于配置 Cipher Suite Filters 的命名空间
sec:cipherSuitesFilter 元素
您可以使用 sec:cipherSuitesFilter
元素来定义密码套件过滤器,它可以是 http:tlsClientParameters
元素或 httpj:tlsServerParameters
元素的子项。一个典型的 sec:cipherSuitesFilter
元素,例 4.1 “sec:cipherSuitesFilter 元素的结构” 中显示的概要结构。
例 4.1. sec:cipherSuitesFilter 元素的结构
<sec:cipherSuitesFilter> <sec:include>RegularExpression</sec:include> <sec:include>RegularExpression</sec:include> ... <sec:exclude>RegularExpression</sec:exclude> <sec:exclude>RegularExpression</sec:exclude> ... </sec:cipherSuitesFilter>
语义
以下语义规则适用于 sec:cipherSuitesFilter
元素:
如果一个
sec:cipherSuitesFilter
元素 没有出现在 端点的配置中(也就是说,它没有来自相关http:conduit
或httpj:engine-factory
元素),则会使用以下默认过滤器:<sec:cipherSuitesFilter> <sec:include>.*_EXPORT_.*</sec:include> <sec:include>.*_EXPORT1024.*</sec:include> <sec:include>.*_DES_.*</sec:include> <sec:include>.*_WITH_NULL_.*</sec:include> </sec:cipherSuitesFilter>
-
如果
sec:cipherSuitesFilter
元素出现在端点的配置中,则默认 排除 所有密码套件。 -
要包括密码套件,请将
sec:include
子元素添加到sec:cipherSuitesFilter
元素。sec:include
元素的内容是匹配一个或多个密码套件名称的正则表达式(例如,请查看 “SunJSSE 支持的密码套件”一节中的密码套件名称)。 要进一步重新定义所选密码套件,您可以在
sec:cipherSuitesFilter
元素中添加sec:exclude
元素。sec:exclude
元素的内容是一个正则表达式,与当前包含的集合中的零个或多个密码套件名称匹配。注意有时,明确排除当前未包含的密码套件是合理的,以便防止意外包含不需要的密码套件。
正则表达式匹配
出现在 sec:include
和 sec:exclude
元素的正则表达式的 grammar 由 Java 正则表达式实用程序定义,java.util.regex.Pattern
。有关marmar的详细描述,请参阅 Java 参考指南 http://download.oracle.com/javase/1.5.0/docs/api/java/util/regex/Pattern.html。
client conduit 示例
以下 XML 配置显示了将密码套件过滤器应用到远程端点( {
WSDLPortNamespace}
PortName )的客户端示例。每当客户端尝试打开此端点的 SSL/TLS 连接时,它会将可用的密码套件限制为 sec:cipherSuitesFilter
元素选择的密码套件。
<beans ... > <http:conduit name="{WSDLPortNamespace}PortName.http-conduit"> <http:tlsClientParameters> ... <sec:cipherSuitesFilter> <sec:include>.*_WITH_3DES_.*</sec:include> <sec:include>.*_WITH_DES_.*</sec:include> <sec:exclude>.*_WITH_NULL_.*</sec:exclude> <sec:exclude>.*_DH_anon_.*</sec:exclude> </sec:cipherSuitesFilter> </http:tlsClientParameters> </http:conduit> <bean id="cxf" class="org.apache.cxf.bus.CXFBusImpl"/> </beans>
4.3. SSL/TLS 协议版本
概述
Apache CXF 支持的 SSL/TLS 协议的版本取决于配置的特定 JSSE 供应商。默认情况下,JSSE 提供商配置为 SUN 的 JSSE 提供商实施。
如果启用 SSL/TLS 安全性,您必须确保显式禁用 SSLv3 协议,以便防止 Poodle 漏洞(CVE-2014-3566)。如需了解更多详细信息,请参阅 JBoss Fuse 6.x 和 JBoss A-MQ 6.x 中的禁用 SSLv3。
SunJSSE 支持的 SSL/TLS 协议版本
表 4.2 “SUN 的 JSSE Provider 支持的 SSL/TLS 协议” 显示 SUN 的 JSSE 提供商支持的 SSL/TLS 协议版本。
表 4.2. SUN 的 JSSE Provider 支持的 SSL/TLS 协议
协议 | 描述 |
---|---|
| 请勿使用!(POODLE 安全漏洞) |
| 请勿使用!(POODLE 安全漏洞) |
| 支持 TLS 版本 1 |
| 支持 TLS 版本 1.1(JDK 7 或更高版本) |
| 支持 TLS 版本 1.2(JDK 7 或更高版本) |
排除特定的 SSL/TLS 协议版本
默认情况下,JSSE 提供商提供的所有 SSL/TLS 协议都可用于 CXF 端点(除了 SSLv2Hello
和 SSLv3
协议外,在从 Fuse 版本 6.2.0 起,CXF 运行时都特别排除了 Poodle 安全漏洞(CVE-2014-3566))。
要排除特定的 SSL/TLS 协议,请使用端点配置中的 sec:excludeProtocols
元素。您可以将 sec:excludeProtocols
元素配置为 httpj:tlsServerParameters
元素的子级。
要排除除 TLS 版本 1.2 外的所有协议,请按如下所示配置 sec:excludeProtocols
元素(假设您使用 JDK 7 或更高版本):
<?xml version="1.0" encoding="UTF-8"?> <beans ... > ... <httpj:engine-factory bus="cxf"> <httpj:engine port="9001"> ... <httpj:tlsServerParameters> ... <sec:excludeProtocols> <sec:excludeProtocol>SSLv2Hello</sec:excludeProtocol> <sec:excludeProtocol>SSLv3</sec:excludeProtocol> <sec:excludeProtocol>TLSv1</sec:excludeProtocol> <sec:excludeProtocol>TLSv1.1</sec:excludeProtocol> </sec:excludeProtocols> </httpj:tlsServerParameters> </httpj:engine> </httpj:engine-factory> ... </beans>
建议您始终排除 SSLv2Hello
和 SSLv3
协议,以防御 Poodle 漏洞(CVE-2014-3566)。
secureSocketProtocol 属性
http:tlsClientParameters
元素和 httpj:tlsServerParameters
元素都支持 secureSocketProtocol
属性,它可让您指定特定的协议。
此属性的语义混淆,但是:此属性会强制 CXF 选择一个支持指定协议的 SSL 供应商,但它不限制供应商只使用指定的协议。因此,端点使用不同于指定的协议来结束。因此,建议您不要使用代码中的 secureSocketProtocol
属性。
第 5 章 WS-Policy 框架
摘要
本章介绍了 WS-Policy 框架的基本概念,定义策略主题和策略断言,并阐述如何组合策略断言来制定策略表达式。
5.1. WS-Policy 简介
概述
WS-Policy 规范 提供了一个通用框架,用于应用策略,修改 Web 服务应用中在运行时连接和通信的语义。Apache CXF 安全性使用 WS-Policy 框架配置消息保护和身份验证要求。
策略和策略参考
指定策略的最简单方法是直接嵌入要应用策略的位置。例如,要将策略与 WSDL 合同中的特定端口关联,您可以按照如下所示指定它:
<wsdl:definitions targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... > ... <wsdl:service name="PingService10"> <wsdl:port name="UserNameOverTransport_IPingService" binding="BindingName"> <wsp:Policy> <!-- Policy expression comes here! --> </wsp:Policy> <soap:address location="SOAPAddress"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
指定策略的一种替代方法是在要应用策略时插入策略参考元素 wsp:PolicyReference
,然后在 XML 文件中的某个其他点插入策略元素 wsp:Policy
。例如,要使用策略引用将策略与特定端口关联,您可以使用类似如下的配置:
<wsdl:definitions targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... > ... <wsdl:service name="PingService10"> <wsdl:port name="UserNameOverTransport_IPingService" binding="BindingName"> <wsp:PolicyReference URI="#PolicyID"/> <soap:address location="SOAPAddress"/> </wsdl:port> </wsdl:service> ... <wsp:Policy wsu:Id="PolicyID"> <!-- Policy expression comes here ... --> </wsp:Policy> </wsdl:definitions>
当策略引用时,wsp:PolicyReference
使用 ID, PolicyID 查找引用的策略(请注意 URI
属性中添加 #
前缀字符)。策略本身 wsp:Policy
必须通过添加属性 wsu:Id="PolicyID"
来识别。
策略主题
与策略关联的实体被称为 策略主题。例如,您可以将策略与端点关联,在这种情况下,端点 为策略主题。可以将多个策略与任何给定策略主题相关联。WS-Policy 框架支持以下策略主题:
服务策略主题
要将策略与服务关联,请插入 < wsp:Policy>
元素或 <wsp:PolicyReference
> 元素作为以下 WSDL 1.1 元素的子元素:
-
WSDL:service
- 将策略应用到该服务提供的所有端口(端点)。
端点策略主题
要将策略与端点关联,请插入 < ;wsp:Policy&
gt; 元素或 < wsp:PolicyReference
> 元素作为以下 WSDL 1.1 元素的子元素:
-
WSDL:portType
- 将策略应用到使用此端口类型的所有端口(端点)。 -
WSDL:binding
- 将策略应用到使用此绑定的所有端口。 -
WSDL:port
- 仅应用此端点的策略。
例如,您可以将策略与端点绑定关联,如下所示(使用策略参考):
<wsdl:definitions targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... > ... <wsdl:binding name="EndpointBinding" type="i0:IPingService"> <wsp:PolicyReference URI="#PolicyID"/> ... </wsdl:binding> ... <wsp:Policy wsu:Id="PolicyID"> ... </wsp:Policy> ... </wsdl:definitions>
操作策略主题
要将策略与操作关联,请插入 < ;wsp:Policy&
gt; 元素或 < wsp:PolicyReference
> 元素作为以下任何 WSDL 1.1 元素的子元素:
-
WSDL:portType/wsdl:operation
-
WSDL:binding/wsdl:operation
例如,您可以将策略与绑定中的操作关联(使用策略引用):
<wsdl:definitions targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... > ... <wsdl:binding name="EndpointBinding" type="i0:IPingService"> <wsdl:operation name="Ping"> <wsp:PolicyReference URI="#PolicyID"/> <soap:operation soapAction="http://xmlsoap.org/Ping" style="document"/> <wsdl:input name="PingRequest"> ... </wsdl:input> <wsdl:output name="PingResponse"> ... </wsdl:output> </wsdl:operation> ... </wsdl:binding> ... <wsp:Policy wsu:Id="PolicyID"> ... </wsp:Policy> ... </wsdl:definitions>
消息策略主题
要将策略与消息关联,请插入 < ;wsp:Policy&
gt; 元素或 < wsp:PolicyReference
> 元素作为以下任何 WSDL 1.1 元素的子元素:
-
WSDL:message
-
WSDL:portType/wsdl:operation/wsdl:input
-
WSDL:portType/wsdl:operation/wsdl:output
-
WSDL:portType/wsdl:operation/wsdl:fault
-
WSDL:binding/wsdl:operation/wsdl:input
-
wsdl:binding/wsdl:operation/wsdl:output
-
WSDL:binding/wsdl:operation/wsdl:fault
例如,您可以将策略与绑定中的消息相关联(使用策略引用):
<wsdl:definitions targetNamespace="http://tempuri.org/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" ... > ... <wsdl:binding name="EndpointBinding" type="i0:IPingService"> <wsdl:operation name="Ping"> <soap:operation soapAction="http://xmlsoap.org/Ping" style="document"/> <wsdl:input name="PingRequest"> <wsp:PolicyReference URI="#PolicyID"/> <soap:body use="literal"/> </wsdl:input> <wsdl:output name="PingResponse"> ... </wsdl:output> </wsdl:operation> ... </wsdl:binding> ... <wsp:Policy wsu:Id="PolicyID"> ... </wsp:Policy> ... </wsdl:definitions>
5.2. 策略示例
概述
通常,ws p:Policy
元素由多个不同的策略设置组成(其中单个策略设置被指定为 策略断言)。因此,由 wsp:Policy
元素定义的策略实际上是一个复合对象。wsp:Policy
元素的内容称为 策略表达式,其中的策略表达式由基本策略断言的各种逻辑组合组成。通过定制策略表达式的语法,您可以确定在运行时必须满足哪些策略断言组合以满足策略的整体要求。
本节详细介绍了策略表达式的语法和语义。
策略断言
策略断言是基本的构建块,可以通过各种方式合并来生成策略。策略断言有两个关键特征:它为策略主题添加了基本功能单元,它代表了在运行时评估的布尔值断言。例如,请考虑以下策略断言,它需要使用请求消息传播 WS-Security username 令牌:
<sp:SupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:UsernameToken/> </wsp:Policy> </sp:SupportingTokens>
当与端点策略主题关联时,此策略断言有以下影响:
- Web 服务端点 marshales/unmarshals the UsernameToken 凭证。
-
在运行时,如果出现 UsernameToken 凭证(在客户端一侧)提供或在传入消息(在服务器端)中接收,策略断言返回为
false
。
请注意,如果策略断言返回为 false
,则不一定会导致错误。特定策略断言的 net effect 取决于它如何插入策略以及如何与其他策略反对。
策略替代
策略是使用策略断言程序构建,它还可使用 wsp:optional 属性以及
和 wsp:
Allwsp:ExactlyOne
元素的各种嵌套组合。组成这些元素的 net effect 就是生成一系列可接受 策略的替代方案。只要满足这些可接受的策略替代方法之一,整个策略也会被验证(等同于 true
)。
wsp:All 元素
当策略断言列表由 wsp:All
元素嵌套时,列表中的所有 策略断言者都必须评估为 true
。例如,请考虑以下验证和授权策略断言组合:
<wsp:Policy wsu:Id="AuthenticateAndAuthorizeWSSUsernameTokenPolicy"> <wsp:All> <sp:SupportingTokens> <wsp:Policy> <sp:UsernameToken/> </wsp:Policy> </sp:SupportingTokens> <sp:SupportingTokens> <wsp:Policy> <sp:SamlToken/> </wsp:Policy> </sp:SupportingTokens> </wsp:All> </wsp:Policy>
如果满足以下条件,则上述策略将满足特定的传入请求:
- 必须存在 WS-Security UsernameToken 凭证 ; 和
- 必须存在 SAML 令牌。
wsp:Policy
元素在语义上相当于 wsp:All
。因此,如果您从上例中删除了 wsp:All
元素,则会获得语义相同的示例
wsp:ExactlyOne 元素
当策略断言列表由 wsp:ExactlyOne
元素嵌套 时,列表中的至少一个 策略断言必须评估为 true
。运行时会出现列表,评估策略断言,直到发现返回为 true
的策略断言。此时,ws p:ExactlyOne
表达式已满足(返回 true
)以及列表中的任何剩余的策略断言。例如,请考虑以下验证策略断言组合:
<wsp:Policy wsu:Id="AuthenticateUsernamePasswordPolicy"> <wsp:ExactlyOne> <sp:SupportingTokens> <wsp:Policy> <sp:UsernameToken/> </wsp:Policy> </sp:SupportingTokens> <sp:SupportingTokens> <wsp:Policy> <sp:SamlToken/> </wsp:Policy> </sp:SupportingTokens> </wsp:ExactlyOne> </wsp:Policy>
如果满足以下条件 之一,上述策略将满足特定的传入请求:
- 存在 WS-Security UsernameToken 凭证; 或者
- 已存在 SAML 令牌。
请注意,特别是,如果两个 凭证类型都存在,在评估其中一个断言后,策略会满足,但不能保证,就实际会被评估。
空策略
一个特殊情形是 空策略,例如 例 5.1 “Empty 策略”。
例 5.1. Empty 策略
<wsp:Policy ... > <wsp:ExactlyOne> <wsp:All/> </wsp:ExactlyOne> </wsp:Policy>
在空策略替代的情况下,< wsp:All
/> 代表了不需要满足任何策略断言的替代选择。换句话说,它总是返回 true
。当 <wsp:All
/> 做为替代版本提供时,即使没有策略断言 也是如此,整个策略也可以被验证
。
null 策略
特殊情况下是 null 策略,其示例如下 例 5.2 “Null 策略”。
例 5.2. Null 策略
<wsp:Policy ... > <wsp:ExactlyOne/> </wsp:Policy>
对于 null 策略替代的,<wsp:ExactlyOne
/> 是不满足的替代选择。换句话说,它总是返回 false
。
普通形式
在实践中,通过嵌套 < ;wsp:All
& gt; 和 <wsp:ExactlyOne
> 元素,您可以生成比较复杂的策略表达式,其中的策略选择很难工作。为方便对策略表达式进行比较,WS-Policy 规格为策略表达式定义了一个规范或 普通形式,以便您能够彻底阅读策略方案列表。每个有效的策略表达式都可以减小到普通形式。
通常,普通表单策略表达式符合 例 5.3 “普通表单语法” 中显示的语法。
例 5.3. 普通表单语法
<wsp:Policy ... > <wsp:ExactlyOne> <wsp:All> <Assertion .../> ... <Assertion .../> </wsp:All> <wsp:All> <Assertion .../> ... <Assertion .../> </wsp:All> ... </wsp:ExactlyOne> </wsp:Policy>
如果每行内容为 < wsp:All>…</wsp:All>
;,代表有效的策略选择。如果上述某个策略替代方案已满足,则整体满足该策略。
第 6 章 消息保护
摘要
本章介绍了以下消息保护机制:防止丢弃(使用加密算法)和保护消息篡改(使用消息摘要算法)。该保护可以在不同的粒度级别和不同的协议层中应用。在传输层,您可以选择将保护应用到消息的所有内容。在 SOAP 层,您可以选择将保护应用到消息的不同部分(正文、标头或附件)。
6.1. 传输层安全性
概述
传输层安全性保护指的是由传输层提供的消息保护(静态和签名)。例如,HTTPS 使用 SSL/TLS 提供加密和消息签名功能。实际上,WS-SecurityPolicy 不适用于 HTTPS 功能集,因为 HTTPS 已经使用 Blueprint XML 配置完全可配置(请参阅 第 3 章 配置 HTTPS)。为 HTTPS 指定传输绑定策略的一个优点是,它可让您在 WSDL 合同中嵌入安全要求。因此,获取 WSDL 合同副本的任何客户端都可以发现作为 WSDL 合同中的端点的传输层安全要求。
如果您在传输层中启用 SSL/TLS 安全性,您必须确保显式禁用 SSLv3 协议,以便防止出现 Poodle 漏洞(CVE-2014-3566)。如需了解更多详细信息,请参阅 JBoss Fuse 6.x 和 JBoss A-MQ 6.x 中的禁用 SSLv3。
先决条件
如果使用 WS-SecurityPolicy 配置 HTTPS 传输,还必须在 Blueprint 配置中相应地配置 HTTPS 安全性。
例 6.1 “蓝图中的客户端 HTTPS 配置” 展示如何配置客户端以使用 HTTPS 传输协议。sec:keyManagers
元素指定客户端自己的证书 alice.pfx
以及 sec:trustManagers
元素指定可信 CA 列表。注意 http:conduit
元素的 name
属性如何使用通配符来匹配端点地址。有关如何在客户端配置 HTTPS 的详情,请参考 第 3 章 配置 HTTPS。
例 6.1. 蓝图中的客户端 HTTPS 配置
<beans xmlns="https://osgi.org/xmlns/blueprint/v1.0.0/" xmlns:http="http://cxf.apache.org/transports/http/configuration" xmlns:sec="http://cxf.apache.org/configuration/security" ... > <http:conduit name="https://.*/UserNameOverTransport.*"> <http:tlsClientParameters disableCNCheck="true"> <sec:keyManagers keyPassword="password"> <sec:keyStore type="pkcs12" password="password" resource="certs/alice.pfx"/> </sec:keyManagers> <sec:trustManagers> <sec:keyStore type="pkcs12" password="password" resource="certs/bob.pfx"/> </sec:trustManagers> </http:tlsClientParameters> </http:conduit> ... </beans>
例 6.2 “蓝图中的服务器 HTTPS 配置” 展示如何将服务器配置为使用 HTTPS 传输协议。sec:keyManagers
元素指定服务器自己的证书,bob.pfx
和 sec:trustManagers
元素指定可信 CA 列表。有关如何在服务器端配置 HTTPS 的详情,请参考 第 3 章 配置 HTTPS。
例 6.2. 蓝图中的服务器 HTTPS 配置
<beans xmlns="https://osgi.org/xmlns/blueprint/v1.0.0/" xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration" xmlns:sec="http://cxf.apache.org/configuration/security" ... > <httpj:engine-factory id="tls-settings"> <httpj:engine port="9001"> <httpj:tlsServerParameters secureSocketProtocol="TLSv1"> <sec:keyManagers keyPassword="password"> <sec:keyStore type="pkcs12" password="password" resource="certs/bob.pfx"/> </sec:keyManagers> <sec:trustManagers> <sec:keyStore type="pkcs12" password="password" resource="certs/alice.pfx"/> </sec:trustManagers> </httpj:tlsServerParameters> </httpj:engine> </httpj:engine-factory> ... </beans>
您必须将 secureSocketProtocol 设置为服务器端的 TLSv1
,以便防止 Poodle 漏洞(CVE-2014-3566)
策略主题
传输绑定策略必须应用到端点策略主体(请参阅 “端点策略主题”一节)。例如,如果带有 ID 的传输绑定策略, UserNameOverTransport_IPingService_policy
,您可以将策略应用到端点绑定中,如下所示:
<wsdl:binding name="UserNameOverTransport_IPingService" type="i0:IPingService"> <wsp:PolicyReference URI="#UserNameOverTransport_IPingService_policy"/> ... </wsdl:binding>
语法
TransportBinding
元素具有以下语法:
<sp:TransportBinding xmlns:sp="..." ... > <wsp:Policy xmlns:wsp="..."> <sp:TransportToken ... > <wsp:Policy> ... </wsp:Policy> ... </sp:TransportToken> <sp:AlgorithmSuite ... > ... </sp:AlgorithmSuite> <sp:Layout ... > ... </sp:Layout> ? <sp:IncludeTimestamp ... /> ? ... </wsp:Policy> ... </sp:TransportBinding>
策略示例
例 6.3 “传输绑定示例” 显示需要使用 HTTPS 传输(由 sp:HttpsToken
元素指定)和 256 位算法套件(由 sp:Basic256
元素指定)的传输绑定示例。
例 6.3. 传输绑定示例
<wsp:Policy wsu:Id="UserNameOverTransport_IPingService_policy"> <wsp:ExactlyOne> <wsp:All> <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:TransportToken> <wsp:Policy> <sp:HttpsToken RequireClientCertificate="false"/> </wsp:Policy> </sp:TransportToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Lax/> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp/> </wsp:Policy> </sp:TransportBinding> ... <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefIssuerSerial/> </wsp:Policy> </sp:Wss10> </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
sp:TransportToken
此元素具有两倍的效果:它要求特定类型的安全令牌,并指示传输如何保护。例如,通过指定 sp:HttpsToken
,这表示连接由 HTTPS 协议保护,安全令牌是 X.509 证书。
sp:AlgorithmSuite
这个元素指定了用于签名和加密的加密算法套件。有关可用算法套件的详情,请参考 第 6.2.7 节 “指定 Algorithm Suite”。
SP:布局
此元素指定是否在 SOAP 消息中添加安全性标头的顺序实施任何条件。sp:Lax
元素指定没有对安全标头顺序实施的条件。sp:Lax
的替代方案是 sp:Strict
,sp:LaxTimestampFirst
, 或 sp:LaxTimestampLast
。
sp:IncludeTimestamp
如果策略中包含此元素,则运行时会将 wsu:Timestamp
元素添加到 wsse:Security
标头。默认情况下 不包含 时间戳。
sp:MustSupportRefKeyIdentifier
此元素指定,安全运行时必须能够处理 密钥标识符 令牌引用,具体如 WS-Security 1.0 规格中指定。键标识符是识别密钥令牌的机制,可以在签名或加密元素中使用。Apache CXF 需要此功能。
sp:MustSupportRefIssuerSerial
此元素指定,安全运行时必须能够处理 Issuer 和 Serial Number 令牌引用,如 WS-Security 1.0 规格中指定。签发者和序列号是识别密钥令牌的机制,可以在签名或加密元素中使用。Apache CXF 需要此功能。
6.2. SOAP 消息保护
6.2.1. SOAP 消息保护简介
概述
通过在 SOAP 编码层而不是传输层应用消息保护,您可以访问更为灵活的保护策略。特别是,因为 SOAP 层知道消息结构,因此您可以在更精细的粒度级别应用保护,例如仅加密并签名那些实际需要保护的标头。此功能允许您支持更复杂的多层架构。例如,一个纯文本标头可能基于中间层(位于安全内部内部),而加密标头可能基于最终目的地(通过不安全的公共网络访问)。
安全绑定
如 WS-SecurityPolicy 规格中所述,以下绑定类型之一可以用来保护 SOAP 信息:
-
SP:TransportBinding
- 传输绑定 是指传输级别提供的消息保护(例如,通过 HTTPS)。此绑定可用于保护任何消息类型,而不仅仅是 SOAP,在前面的部分 第 6.1 节 “传输层安全性” 中详细介绍。 -
SP:AsymmetricBinding
- 非对称绑定 是指 SOAP 消息编码层提供的消息保护,其中保护功能使用非对称加密(也称为公钥加密)实施。 -
SP:SymmetricBinding
- 对称绑定 是指 SOAP 消息编码层提供的消息保护,其中保护功能将使用对称加密实施。对称加密示例是由 WS-SecureConversation 和 Kerberos 令牌提供的令牌。
消息保护
以下保护数量可应用于部分或全部消息:
- 加密.
- 签名.
- 签名+encryption(在加密前签名)。
- encryption+signing(加密,在签名前)。
这些数量保护可以是在单个消息中任意组合的保护。因此,消息的某些部分只需加密,而消息的其他部分则只签名,消息的其他部分则也可被签名和加密。也可以将消息的部分保留为不受保护。
应用消息保护的最灵活选项可在 SOAP 层提供(sp:AsymmetricBinding
或 sp:SymmetricBinding
)。传输层(sp:TransportBinding
)只为您提供 对整个 消息应用保护的选项。
指定要保护的消息的部分
目前,Apache CXF 允许您为 SOAP 消息的以下部分签名或加密:
-
body-sign 和/or 加密 SOAP 消息中的
soap:BODY
元素。 - 标头 -sign 和/或加密一个或多个 SOAP 邮件标题。您可以单独指定每个标头的保护质量。
- Attachments-sign 和/或加密 SOAP 消息中的所有附件。
- 元素- 在 SOAP 消息中签名和/或加密特定 XML 元素。
配置角色
不是使用策略指定消息保护所需的所有详情。这些策略主要用于指定服务所需的质量保护。必须使用一个独立的产品特定机制提供支持(如安全令牌、密码等)的详情。实际上,这意味着在 Apache CXF 中,必须在 Blueprint XML 配置文件中提供一些支持配置详细信息。详情请查看 第 6.2.6 节 “提供加密密钥和签名密钥”。
6.2.2. 基本签名和加密(cenario)
概述
此处描述的场景是客户端-服务器应用程序,其中将 非对称绑定策略 设置为加密并签名在客户端和服务器之间传输的消息的 SOAP 正文。
示例情境
图 6.1 “基本签名和加密(cenario)” 演示了基本签名和加密场景的概述,具体是通过将非对称绑定策略与 WSDL 合同中的端点相关联来指定。
图 6.1. 基本签名和加密(cenario)
场景步骤
当 图 6.1 “基本签名和加密(cenario)” 中的客户端在接收者端点上调用同步操作时,请求和回复信息会按如下方式处理:
当传出请求消息通过 WS-SecurityPolicy 处理程序时,处理程序会根据客户端的非对称绑定策略中指定的策略来处理消息。在本例中,处理程序执行以下处理:
- 使用 Bob 的公钥加密消息的 SOAP 正文。
- 使用 Alice 的私钥签署加密的 SOAP 正文。
当传入的请求消息通过服务器的 WS-SecurityPolicy 处理程序时,处理程序会根据服务器的非对称绑定策略中指定的策略来处理消息。在本例中,处理程序执行以下处理:
- 使用 Alice 的公钥验证签名。
- 使用 Bob 的私钥解密 SOAP 正文。
当传出回复消息通过服务器的 WS-SecurityPolicy 处理程序时,处理程序将执行以下处理:
- 使用 Alice 的公钥加密消息的 SOAP 正文。
- 使用 Bob 的私钥签署加密的 SOAP 正文。
当传入的回复消息通过客户端的 WS-SecurityPolicy 处理程序时,处理程序将执行以下处理:
- 使用 Bob 的公钥验证签名。
- 使用 Alice 的私钥解密 SOAP 正文。
6.2.3. 指定 AsymmetricBinding 策略
概述
非对称绑定策略使用非对称密钥算法(公钥/私钥组合)实现 SOAP 消息保护,并在 SOAP 层这样做。非对称绑定的加密和签名算法与 SSL/TLS 使用的加密和签名算法类似。然而,一个关键区别在于,SOAP 消息保护允许您选择消息的特定部分来保护(例如,单个标头、正文或附加),而传输层安全性则只能在整个消息上运行。
策略主题
非对称绑定策略必须应用到端点策略主体(请参阅 “端点策略主题”一节)。例如,如果带有 ID 的非对非对称绑定策略( MutualCertificate10SignEncrypt_IPingService_policy
),您可以按照以下方法应用策略到端点绑定中:
<wsdl:binding name="MutualCertificate10SignEncrypt_IPingService" type="i0:IPingService">
<wsp:PolicyReference URI="#MutualCertificate10SignEncrypt_IPingService_policy"/>
...
</wsdl:binding>
语法
AsymmetricBinding
元素使用以下语法:
<sp:AsymmetricBinding xmlns:sp="..." ... > <wsp:Policy xmlns:wsp="..."> ( <sp:InitiatorToken> <wsp:Policy> ... </wsp:Policy> </sp:InitiatorToken> ) | ( <sp:InitiatorSignatureToken> <wsp:Policy> ... </wsp:Policy> </sp:InitiatorSignatureToken> <sp:InitiatorEncryptionToken> <wsp:Policy> ... </wsp:Policy> </sp:InitiatorEncryptionToken> ) ( <sp:RecipientToken> <wsp:Policy> ... </wsp:Policy> </sp:RecipientToken> ) | ( <sp:RecipientSignatureToken> <wsp:Policy> ... </wsp:Policy> </sp:RecipientSignatureToken> <sp:RecipientEncryptionToken> <wsp:Policy> ... </wsp:Policy> </sp:RecipientEncryptionToken> ) <sp:AlgorithmSuite ... > ... </sp:AlgorithmSuite> <sp:Layout ... > ... </sp:Layout> ? <sp:IncludeTimestamp ... /> ? <sp:EncryptBeforeSigning ... /> ? <sp:EncryptSignature ... /> ? <sp:ProtectTokens ... /> ? <sp:OnlySignEntireHeadersAndBody ... /> ? ... </wsp:Policy> ... </sp:AsymmetricBinding>
策略示例
例 6.4 “Asymmetric Binding 的示例” 演示了支持使用签名和加密的非对称绑定的示例,其中签名和加密是使用公钥/私钥对(使用非对称加密)进行的签名和加密。此示例不指定消息的哪些部分应该被签名并加密。有关如何进行此操作的详情,请参考 第 6.2.5 节 “指定到加密和签名的消息部分”。
例 6.4. Asymmetric Binding 的示例
<wsp:Policy wsu:Id="MutualCertificate10SignEncrypt_IPingService_policy"> <wsp:ExactlyOne> <wsp:All> <sp:AsymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:InitiatorToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:InitiatorToken> <sp:RecipientToken> <wsp:Policy> <sp:X509Token sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never"> <wsp:Policy> <sp:WssX509V3Token10/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:RecipientToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Lax/> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp/> <sp:EncryptSignature/> <sp:OnlySignEntireHeadersAndBody/> </wsp:Policy> </sp:AsymmetricBinding> <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefIssuerSerial/> </wsp:Policy> </sp:Wss10> </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
sp:InitiatorToken
initiator 令牌 引用发起方拥有的公钥/私钥-对。此令牌使用如下:
- 令牌的私钥签名信息从启动器发送到接收者。
- 令牌的公钥验证接收方收到的签名。
- 令牌的公钥加密从接收者发送到启动器的消息。
- 令牌的私钥解密发起方接收的消息。
混淆,此令牌由发起方 和 接收者使用。但是,只有启动器有权访问私钥,因此在这种情况下,令牌可以被认为是属于发起方。在 第 6.2.2 节 “基本签名和加密(cenario)” 中,initiator 令牌是证书 Alice。
这个元素应包含嵌套的 wsp:Policy
元素和 sp:X509Token
元素,如下所示。sp:IncludeToken
属性设为 AlwaysToRecipient
,它指示运行时包含 Alice 的公钥,并将每个消息发送到接收者。如果接收者希望使用启动器的证书来执行身份验证,这个选项很有用。最深嵌套的元素 WssX509V3Token10
是可选的。它指定 X.509 证书应符合哪些规格版本。此处可以指定以下替代(或 none):
- sp:WssX509V3Token10
- 此可选元素是一个策略断言,表示应使用 X509 版本 3 令牌。
- sp:WssX509Pkcs7Token10
- 此可选元素是一个策略断言,表示应使用 X509 PKCS7 令牌。
- sp:WssX509PkiPathV1Token10
- 此可选元素是一个策略断言,表示应使用 X509 PKI Path Version 1 令牌。
- sp:WssX509V1Token11
- 此可选元素是一个策略断言,表示应使用 X509 版本 1 令牌。
- sp:WssX509V3Token11
- 此可选元素是一个策略断言,表示应使用 X509 版本 3 令牌。
- sp:WssX509Pkcs7Token11
- 此可选元素是一个策略断言,表示应使用 X509 PKCS7 令牌。
- sp:WssX509PkiPathV1Token11
- 此可选元素是一个策略断言,表示应使用 X509 PKI Path Version 1 令牌。
sp:RecipientToken
接收者令牌 引用由接收者拥有的公钥/私钥-对。此令牌使用如下:
- 令牌的公钥加密从启动器发送到接收者的消息。
- 令牌的私钥解密接收方接收的消息。
- 令牌的私钥签名从接收者发送到发起方。
- 令牌的公钥验证发起方接收的签名。
混淆,该令牌由接收者 和 启动器使用。但是,只有接收者可以访问私钥,因此使用这个意义,令牌可以被认为属于接收者。在 第 6.2.2 节 “基本签名和加密(cenario)” 中,接收者令牌是证书 Bob。
这个元素应包含嵌套的 wsp:Policy
元素和 sp:X509Token
元素,如下所示。sp:IncludeToken
属性设为 Never
,因为不需要在回复消息中包含 Bob 的公钥。
在 Apache CXF 中,不需要在消息中发送 Bob 或 Alice 的令牌,因为 Bob 的证书和 Alice 的证书在两端均提供,请参阅 第 6.2.6 节 “提供加密密钥和签名密钥”。
sp:AlgorithmSuite
这个元素指定了用于签名和加密的加密算法套件。有关可用算法套件的详情,请参考 第 6.2.7 节 “指定 Algorithm Suite”。
SP:布局
此元素指定是否在 SOAP 消息中添加安全性标头的顺序实施任何条件。sp:Lax
元素指定没有对安全标头顺序实施的条件。sp:Lax
的替代方案是 sp:Strict
,sp:LaxTimestampFirst
, 或 sp:LaxTimestampLast
。
sp:IncludeTimestamp
如果策略中包含此元素,则运行时会将 wsu:Timestamp
元素添加到 wsse:Security
标头。默认情况下 不包含 时间戳。
sp:EncryptBeforeSigning
如果消息部分同时受到加密和签名,则需要指定执行这些操作的顺序。默认顺序是在加密前签名。但是,如果您将这个元素包含在非对称策略中,则这个顺序将更改为在签名前加密。
隐式,此元素也会影响解密和签名验证操作的顺序。例如,如果在加密前发送消息符号的发件人,则消息的接收器必须在验证签名前进行解密。
sp:EncryptSignature
这个元素指定必须加密消息签名(通过加密令牌,如 第 6.2.6 节 “提供加密密钥和签名密钥”所述)。默认为 false。
邮件签名 是通过签署消息的各种部分直接获取的签名,如消息正文、邮件标题或独立元素(请参阅 第 6.2.5 节 “指定到加密和签名的消息部分”)。有时,消息签名被称为 主签名,因为 WS-SecurityPolicy 规格还支持端到端支持令牌的概念,该令牌用于签署主签名。因此,如果 sp:EndorsingTokens
元素应用于端点,您可以有一个签名链:主签名(签名信息本身)和辅助签名(为主签名签名签名)。
有关各种支持令牌的详情,请参考 “SupportingTokens assertions”一节。
sp:ProtectTokens
此元素指定签名必须包含用于生成该签名的令牌。默认为 false。
sp:OnlySignEntireHeadersAndBody
此元素指定签名 只应用于 整个正文或整个标头,不适用于标题的正文或子元素的子元素。启用这个选项时,您可以有效地防止使用 sp:SignedElements
断言(请参阅 第 6.2.5 节 “指定到加密和签名的消息部分”)。
6.2.4. 指定 SymmetricBinding 策略
概述
对称绑定策略使用对称密钥算法(共享 secret 密钥)实现 SOAP 消息保护,并在 SOAP 层这样做。对称绑定的示例是 Kerberos 协议和 WS-SecureConversation 协议。
目前,Apache CXF 只支持 对称绑定中的 WS-SecureConversation 令牌。
策略主题
对称绑定策略必须应用到端点策略主题(请参阅 “端点策略主题”一节)。例如,如果带有 ID 的对称绑定策略, SecureConversation_MutualCertificate10SignEncrypt_IPingService_policy
,您可以将策略应用到端点绑定中,如下所示:
<wsdl:binding name="SecureConversation_MutualCertificate10SignEncrypt_IPingService" type="i0:IPingService">
<wsp:PolicyReference URI="#SecureConversation_MutualCertificate10SignEncrypt_IPingService_policy"/>
...
</wsdl:binding>
语法
SymmetricBinding
元素具有以下语法:
<sp:SymmetricBinding xmlns:sp="..." ... > <wsp:Policy xmlns:wsp="..."> ( <sp:EncryptionToken ... > <wsp:Policy> ... </wsp:Policy> </sp:EncryptionToken> <sp:SignatureToken ... > <wsp:Policy> ... </wsp:Policy> </sp:SignatureToken> ) | ( <sp:ProtectionToken ... > <wsp:Policy> ... </wsp:Policy> </sp:ProtectionToken> ) <sp:AlgorithmSuite ... > ... </sp:AlgorithmSuite> <sp:Layout ... > ... </sp:Layout> ? <sp:IncludeTimestamp ... /> ? <sp:EncryptBeforeSigning ... /> ? <sp:EncryptSignature ... /> ? <sp:ProtectTokens ... /> ? <sp:OnlySignEntireHeadersAndBody ... /> ? ... </wsp:Policy> ... </sp:SymmetricBinding>
策略示例
例 6.5 “Symmetric Binding 示例” 演示了对称绑定的示例,它支持使用签名和加密的消息保护,其中签名和加密是使用单个对称密钥(即使用对称加密)进行的。此示例不指定消息的哪些部分应该被签名并加密。有关如何进行此操作的详情,请参考 第 6.2.5 节 “指定到加密和签名的消息部分”。
例 6.5. Symmetric Binding 示例
<wsp:Policy wsu:Id="SecureConversation_MutualCertificate10SignEncrypt_IPingService_policy"> <wsp:ExactlyOne> <wsp:All> <sp:SymmetricBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:ProtectionToken> <wsp:Policy> <sp:SecureConversationToken> ... </sp:SecureConversationToken> </wsp:Policy> </sp:ProtectionToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:Basic256/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Lax/> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp/> <sp:EncryptSignature/> <sp:OnlySignEntireHeadersAndBody/> </wsp:Policy> </sp:SymmetricBinding> <sp:Wss10 xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:MustSupportRefKeyIdentifier/> <sp:MustSupportRefIssuerSerial/> </wsp:Policy> </sp:Wss10> ... </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
sp:ProtectionToken
此元素指定一个对称令牌,用于签名和加密消息。例如,您可以在此处指定 WS-SecureConversation 令牌。
如果要使用不同令牌来签名和加密操作,请使用 sp:SignatureToken
元素和 sp:EncryptionToken
元素代替这个元素。
sp:SignatureToken
此元素指定一个对称令牌,用于签名消息。它应该与 sp:EncryptionToken
元素结合使用。
sp:EncryptionToken
此元素指定一个对称令牌来加密消息。它应该与 sp:SignatureToken
元素结合使用。
sp:AlgorithmSuite
这个元素指定了用于签名和加密的加密算法套件。有关可用算法套件的详情,请参考 第 6.2.7 节 “指定 Algorithm Suite”。
SP:布局
此元素指定是否在 SOAP 消息中添加安全性标头的顺序实施任何条件。sp:Lax
元素指定没有对安全标头顺序实施的条件。sp:Lax
的替代方案是 sp:Strict
,sp:LaxTimestampFirst
, 或 sp:LaxTimestampLast
。
sp:IncludeTimestamp
如果策略中包含此元素,则运行时会将 wsu:Timestamp
元素添加到 wsse:Security
标头。默认情况下 不包含 时间戳。
sp:EncryptBeforeSigning
当消息部分同时受到加密和签名条件时,需要指定执行这些操作的顺序。默认顺序是在加密前签名。但是,如果您将这个元素包含在对称策略中,则这个顺序被修改为在签名前加密。
隐式,此元素也会影响解密和签名验证操作的顺序。例如,如果在加密前发送消息符号的发件人,则消息的接收器必须在验证签名前进行解密。
sp:EncryptSignature
此元素指定邮件签名必须经过加密。默认为 false。
sp:ProtectTokens
此元素指定签名必须包含用于生成该签名的令牌。默认为 false。
sp:OnlySignEntireHeadersAndBody
此元素指定签名 只应用于 整个正文或整个标头,不适用于标题的正文或子元素的子元素。启用这个选项时,您可以有效地防止使用 sp:SignedElements
断言(请参阅 第 6.2.5 节 “指定到加密和签名的消息部分”)。
6.2.5. 指定到加密和签名的消息部分
概述
加密和签名提供了两种类型的保护:机密性和完整性。WS-SecurityPolicy 保护断言被用来指定消息的哪些部分受到保护。有关保护机制的详情,其他机制的详情会在相关的绑定策略中单独指定(请参阅 x第 6.2.3 节 “指定 AsymmetricBinding 策略”、第 6.2.4 节 “指定 SymmetricBinding 策略” 和 第 6.1 节 “传输层安全性”。
此处描述的保护断言要与 SOAP 安全性结合使用,因为它们适用于 SOAP 消息的功能。然而,这些策略也可受到传输绑定(如 HTTPS)的要求,对整个 消息应用保护,而不是对特定部分提供支持。
策略主题
必须将一个保护断言应用到 消息策略主题 (请参阅 “消息策略主题”一节)。换句话说,它必须放在 wsdl:input
中、wsdl:output
或 wsdl:fault
元素 in an WSDL 绑定中。例如,如果带有 ID 的保护策略, MutualCertificate10SignEncrypt_IPingService_header_Input_policy
,您可以将策略应用到 wsdl:input
消息部分,如下所示:
<wsdl:operation name="header">
<soap:operation soapAction="http://InteropBaseAddress/interop/header" style="document"/>
<wsdl:input name="headerRequest">
<wsp:PolicyReference
URI="#MutualCertificate10SignEncrypt_IPingService_header_Input_policy"/>
<soap:header message="i0:headerRequest_Headers" part="CustomHeader" use="literal"/>
<soap:body use="literal"/>
</wsdl:input>
...
</wsdl:operation>
保护断言
Apache CXF 支持以下 WS-SecurityPolicy 保护断言:
-
SignedParts
-
EncryptedParts
-
SignedElements
-
EncryptedElements
-
ContentEncryptedElements
-
RequiredElements
-
RequiredParts
语法
SignedParts
元素使用以下语法:
<sp:SignedParts xmlns:sp="..." ... > <sp:Body />? <sp:Header Name="xs:NCName"? Namespace="xs:anyURI" ... />* <sp:Attachments />? ... </sp:SignedParts>
EncryptedParts
元素使用以下语法:
<sp:EncryptedParts xmlns:sp="..." ... > <sp:Body/>? <sp:Header Name="xs:NCName"? Namespace="xs:anyURI" ... />* <sp:Attachments />? ... </sp:EncryptedParts>
策略示例
例 6.6 “完整性和加密策略断言” 显示合并两个保护断言的策略:签名部分断言和加密部分断言。当此策略应用到消息部分时,受影响的消息正文会被签名并加密。另外,名为 CustomHeader
的消息标头被签名。
例 6.6. 完整性和加密策略断言
<wsp:Policy wsu:Id="MutualCertificate10SignEncrypt_IPingService_header_Input_policy"> <wsp:ExactlyOne> <wsp:All> <sp:SignedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <sp:Body/> <sp:Header Name="CustomHeader" Namespace="http://InteropBaseAddress/interop"/> </sp:SignedParts> <sp:EncryptedParts xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <sp:Body/> </sp:EncryptedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
sp:Body
此元素指定保护(静态或签名)应用于消息的正文。保护应用于 整个 消息正文:即 soap:Body
元素、其属性及其内容。
sp:Header
此元素指定,使用 Namespace
属性和命名空间将保护应用到标题的本地名称指定的 SOAP 标头。保护应用于 整个 邮件标头,包括其属性及其内容。
sp:Attachments
此元素指定 所有带有 Attachments(SwA)附加的 SOAP 都受到保护。
6.2.6. 提供加密密钥和签名密钥
概述
标准 WS-SecurityPolicy 策略是为了在一些详细信息中指定 安全要求 :例如,安全协议、安全算法、令牌类型、身份验证要求等等。但是,标准策略断言不提供指定相关安全数据的任何机制,如密钥和凭证。WS-SecurityPolicy 期望通过专有机制提供必要的安全数据。在 Apache CXF 中,相关的安全数据通过 Blueprint XML 配置提供。
配置加密密钥和签名密钥
您可以通过在客户端的请求上下文或端点上下文中设置属性来指定应用程序的加密密钥和签名密钥(请参阅 “为 Blueprint 配置添加加密和签名属性”一节)。您可以设置的属性显示在 表 6.1 “加密和签名属性” 中。
表 6.1. 加密和签名属性
属性 | 描述 |
---|---|
|
WSS4J 属性文件/对象,包含用于配置签名密钥存储(也用于解密)和 |
| (可选) 要使用的签名密钥存储中密钥的用户名或别名。若不指定,则使用属性文件中设置的别名。如果也未设置,并且密钥存储仅包含一个密钥,则将使用该密钥。 |
|
WSS4J 属性文件/对象,包含用于配置加密密钥存储(也用于验证签名)和 |
| (可选) 加密密钥存储中要使用的密钥的用户名或别名。若不指定,则使用属性文件中设置的别名。如果也未设置,并且密钥存储仅包含一个密钥,则将使用该密钥。 |
上述属性的名称不会被正确选择,因为它们无法准确反映它们的用途。由 security.signature.properties
指定的密钥实际上用于 签名和 解密。由 security.encryption.properties
指定的密钥实际上用于加密 和 验证签名。
为 Blueprint 配置添加加密和签名属性
在 Apache CXF 应用程序中使用任何 WS-Policy 策略前,您必须将策略功能添加到默认的 CXF 总线中。将 p:policies
元素添加到 CXF 总线,如以下 Blueprint 配置片段所示:
<beans xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xmlns:cxf="http://cxf.apache.org/core"
xmlns:p="http://cxf.apache.org/policy" ... >
<cxf:bus>
<cxf:features>
<p:policies/>
<cxf:logging/>
</cxf:features>
</cxf:bus>
...
</beans>
以下示例演示了如何在指定服务类型的代理中添加签名和加密属性(该服务名称通过 jaxws:client
元素的 name
属性指定)。这些属性存储在 WSS4J 属性文件中,其中 alice.properties
包含签名密钥的属性,bob.properties
包含加密密钥的属性。
<beans ... > <jaxws:client name="{http://InteropBaseAddress/interop}MutualCertificate10SignEncrypt_IPingService" createdFromAPI="true"> <jaxws:properties> <entry key="ws-security.signature.properties" value="etc/alice.properties"/> <entry key="ws-security.encryption.properties" value="etc/bob.properties"/> </jaxws:properties> </jaxws:client> ... </beans>
实际上,虽然属性名称没有明显,但每个密钥都用于客户端的两个不同的目的:
alice.properties
(即security.signature.properties
指定的密钥)在客户端中使用,如下所示:- 用于签名传出消息。
- 用于解密传入消息。
Bob.properties
(即security.encryption.properties
)在客户端中使用,如下所示:- 用于加密传出消息。
- 在传入信息中验证签名。
如果您发现这个混淆,请参阅 第 6.2.2 节 “基本签名和加密(cenario)” 以获得更详细的说明。
以下示例演示了如何在 JAX-WS 端点中添加签名和加密属性。属性文件 bob.properties
包含签名密钥和属性文件 alice.properties
的属性,包含加密密钥的属性(这是客户端配置不良)。
<beans ... > <jaxws:endpoint name="{http://InteropBaseAddress/interop}MutualCertificate10SignEncrypt_IPingService" id="MutualCertificate10SignEncrypt" address="http://localhost:9002/MutualCertificate10SignEncrypt" serviceName="interop:PingService10" endpointName="interop:MutualCertificate10SignEncrypt_IPingService" implementor="interop.server.MutualCertificate10SignEncrypt"> <jaxws:properties> <entry key="security.signature.properties" value="etc/bob.properties"/> <entry key="security.encryption.properties" value="etc/alice.properties"/> </jaxws:properties> </jaxws:endpoint> ... </beans>
每个密钥都用于服务器端的两个不同目的:
Bob.properties
(即security.signature.properties
指定的密钥)在服务器端使用,如下所示:- 用于签名传出消息。
- 用于解密传入消息。
alice.properties
(即security.encryption.properties
)在服务器端使用,如下所示:- 用于加密传出消息。
- 在传入信息中验证签名。
定义 WSS4J 属性文件
Apache CXF 使用 WSS4J 属性文件加载加密和签名所需的公钥和私钥。表 6.2 “WSS4J 密钥存储属性” 描述您可以在这些文件中设置的属性。
表 6.2. WSS4J 密钥存储属性
属性 | 描述 |
---|---|
|
指定
此表中的其余属性特定于 |
|
(可选) 要使用的 JSSE 密钥存储提供程序的名称。默认密钥存储提供程序是 Bouncy Castle。您可以通过将此属性设置为 |
|
Bouncy Castle 密钥存储提供程序支持以下密钥存储: |
| 指定要加载的密钥存储文件的位置,其位置相对于 Classpath。 |
|
(可选) 如果密钥存储类型为 |
| 此属性指定的密码用于两个目的: 解锁密钥存储(密钥存储密码)并解密存储在密钥存储中的私钥(私钥密码)。因此,密钥存储密码必须与私钥密码相同。 |
例如,etc/alice.properties
文件包含用于加载 PKCS#12 文件 certs/alice.pfx
的属性设置,如下所示:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.type=PKCS12 org.apache.ws.security.crypto.merlin.keystore.password=password org.apache.ws.security.crypto.merlin.keystore.file=certs/alice.pfx
etc/bob.properties
文件包含用于加载 PKCS#12 文件 certs/bob.pfx
的属性设置,如下所示:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.password=password # for some reason, bouncycastle has issues with bob.pfx org.apache.ws.security.crypto.merlin.keystore.provider=SunJSSE org.apache.ws.security.crypto.merlin.keystore.type=PKCS12 org.apache.ws.security.crypto.merlin.keystore.file=certs/bob.pfx
编程加密密钥和签名密钥
加载加密密钥和签名密钥的替代方法是使用 表 6.3 “指定 Crypto 对象的属性” 中显示的属性来指定加载相关键的 Crypto
对象。这要求您自己提供 WSS4J Crypto
接口的实施,即 org.apache.ws.security.components.crypto.Crypto
。
表 6.3. 指定 Crypto 对象的属性
属性 | 描述 |
---|---|
|
指定负责加载用于签名和解密消息的密钥的 |
|
指定 |
WSS4J Crypto 接口
例 6.7 “WSS4J Crypto 接口” 显示您可以实现的 Crypto
接口的定义(如果您想要按编程提供加密密钥和签名密钥)。如需更多信息,请参阅 WSS4J 主页。
例 6.7. WSS4J Crypto 接口
// Java package org.apache.ws.security.components.crypto; import org.apache.ws.security.WSSecurityException; import java.io.InputStream; import java.math.BigInteger; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; public interface Crypto { X509Certificate loadCertificate(InputStream in) throws WSSecurityException; X509Certificate[] getX509Certificates(byte[] data, boolean reverse) throws WSSecurityException; byte[] getCertificateData(boolean reverse, X509Certificate[] certs) throws WSSecurityException; public PrivateKey getPrivateKey(String alias, String password) throws Exception; public X509Certificate[] getCertificates(String alias) throws WSSecurityException; public String getAliasForX509Cert(Certificate cert) throws WSSecurityException; public String getAliasForX509Cert(String issuer) throws WSSecurityException; public String getAliasForX509Cert(String issuer, BigInteger serialNumber) throws WSSecurityException; public String getAliasForX509Cert(byte[] skiBytes) throws WSSecurityException; public String getDefaultX509Alias(); public byte[] getSKIBytesFromCert(X509Certificate cert) throws WSSecurityException; public String getAliasForX509CertThumb(byte[] thumb) throws WSSecurityException; public KeyStore getKeyStore(); public CertificateFactory getCertificateFactory() throws WSSecurityException; public boolean validateCertPath(X509Certificate[] certs) throws WSSecurityException; public String[] getAliasesForDN(String subjectDN) throws WSSecurityException; }
6.2.7. 指定 Algorithm Suite
概述
算法套件是用来执行诸如签名、加密、生成消息摘要等操作的一种一致加密算法集合。
为了参考目的,本节描述了 WS-SecurityPolicy 规范定义的算法套件。但是,是否提供特定的算法套件,这取决于底层的安全供应商。Apache CXF 安全性基于可插拔 Java Cryptography Extension(JCE)和 Java 安全套接字扩展(JSSE)层。默认情况下,Apache CXF 配置有 Sun 的 JSSE 提供者,它支持 Sun JSSE 参考指南 中 附录 A 所述的密码套件。
语法
AlgorithmSuite
元素具有以下语法:
<sp:AlgorithmSuite xmlns:sp="..." ... > <wsp:Policy xmlns:wsp="..."> (<sp:Basic256 ... /> | <sp:Basic192 ... /> | <sp:Basic128 ... /> | <sp:TripleDes ... /> | <sp:Basic256Rsa15 ... /> | <sp:Basic192Rsa15 ... /> | <sp:Basic128Rsa15 ... /> | <sp:TripleDesRsa15 ... /> | <sp:Basic256Sha256 ... /> | <sp:Basic192Sha256 ... /> | <sp:Basic128Sha256 ... /> | <sp:TripleDesSha256 ... /> | <sp:Basic256Sha256Rsa15 ... /> | <sp:Basic192Sha256Rsa15 ... /> | <sp:Basic128Sha256Rsa15 ... /> | <sp:TripleDesSha256Rsa15 ... /> | ...) <sp:InclusiveC14N ... /> ? <sp:SOAPNormalization10 ... /> ? <sp:STRTransform10 ... /> ? (<sp:XPath10 ... /> | <sp:XPathFilter20 ... /> | <sp:AbsXPath ... /> | ...)? ... </wsp:Policy> ... </sp:AlgorithmSuite>
算法套件断言支持大量替代算法(例如 Basic256
)。有关算法套件的替代方案的详情,请参考 表 6.4 “算法套件”。
算法套件
表 6.4 “算法套件” 提供 WS-SecurityPolicy 支持的算法套件概述。列标题指向不同类型的加密算法,如下所示:\[Dig] 是摘要算法;\[Enc] 是加密算法;\[Sym KW] 是对称密钥包装算法;\[Asym KW] 是非对称密钥包装算法; \[Enc KD] 是加密密钥的算法;[Sym KW] 是签名算法。
表 6.4. 算法套件
算法套件 | \[Dig] | \[Enc] | \[Sym KW] | \[Asym KW] | \[Enc KD] | \[Sig KD] |
---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
加密算法的类型
WS-SecurityPolicy 支持以下加密算法:
对称密钥签名
对称密钥签名属性 [Sym Sig] 指定使用对称密钥生成签名的算法。WS-SecurityPolicy 指定始终使用 HmacSha1
算法。
HmacSha1
算法由以下 URI 识别:
http://www.w3.org/2000/09/xmldsig#hmac-sha1
非对称密钥签名
非对称密钥签名属性 [Asym Sig] 指定使用非对称密钥生成签名的算法。WS-SecurityPolicy 指定始终使用 RsaSha1
算法。
RsaSha1
算法由以下 URI 识别:
http://www.w3.org/2000/09/xmldsig#rsa-sha1
摘要
digest 属性 [Dig] 指定用于生成消息摘要值的算法。WS-SecurityPolicy 支持两种替代摘要算法: Sha1
和 Sha256
。
Sha1
算法由以下 URI 识别:
http://www.w3.org/2000/09/xmldsig#sha1
Sha256
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#sha256
Encryption
加密属性 [Enc] 指定用于加密数据的算法。WS-SecurityPolicy 支持以下加密算法: Aes256
、Aes192
、Aes128
、TripleDes
。
Aes256
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#aes256-cbc
Aes192
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#aes192-cbc
Aes128
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#aes128-cbc
TripleDes
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#tripledes-cbc
对称密钥嵌套
对称密钥嵌套属性 [Sym KW] 指定用于签名和加密对称密钥的算法。WS-SecurityPolicy 支持以下对称密钥嵌套算法: KwAes256
、KwAes192
、KwAes128
、KwTripleDes
。
KwAes256
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#kw-aes256
KwAes192
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#kw-aes192
KwAes128
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#kw-aes128
KwTripleDes
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#tripledes-cbc
非对称密钥换行
非对称密钥换行属性 [Asym KW] 指定用于签名和加密非对称密钥的算法。WS-SecurityPolicy 支持以下非对称密钥嵌套算法: KwRsaOaep
、KwRsa15
。
KwRsaOaep
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p
KwRsa15
算法由以下 URI 识别:
http://www.w3.org/2001/04/xmlenc#rsa-1_5
computed 密钥
computed 键属性 [Comp Key] 指定用于计算派生密钥的算法。当安全方与共享密钥通信(例如,使用 WS-SecureConvers 时)时,建议使用一个派生密钥而不是原始共享密钥,以避免通过托管第三方公开大量数据以供分析。WS-SecurityPolicy 指定始终使用 PSha1
算法。
PSha1
算法由以下 URI 识别:
http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512/dk/p_sha1
加密密钥分离
加密密钥 derivation 属性 [Enc KD] 指定用于计算派生加密密钥的算法。WS-SecurityPolicy 支持以下加密密钥分离算法: PSha1L256
、PSha1L192
、PSha1L128
。
PSha1
算法由以下 URI 识别(同一算法用于 PSha1L256
、PSha1L192
和 PSha1L128
;只有密钥长度不同):
http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512/dk/p_sha1
签名密钥分离
签名密钥 derivation 属性 [Sig KD] 指定用于计算派生签名密钥的算法。WS-SecurityPolicy 支持以下签名密钥分离算法: PSha1L192
、PSha1L128
。
密钥长度属性
表 6.5 “密钥长度属性” 显示 WS-SecurityPolicy 支持的最小和最大密钥长度。
表 6.5. 密钥长度属性
属性 | 密钥长度 |
---|---|
最小对称密钥长度 [Min SKL] | 128, 192, 256 |
最大对称密钥长度 [Max SKL] | 256 |
最小非对称密钥长度 [Min AKL] | 1024 |
最大非对称密钥长度 [Max AKL] | 4096 |
最小对称密钥长度的值 [Min SKL] 取决于选择哪个算法套件。
第 7 章 身份验证
摘要
本章论述了如何在 Apache CXF 应用程序中使用策略配置身份验证。目前,SOAP 层唯一支持的凭据类型是 WS-Security UsernameToken。
7.1. 身份验证简介
概述
在 Apache CXF 中,可以通过 WSDL 合同中的策略组合以及 Blueprint XML 中的配置设置将应用程序设置为使用身份验证。
请记住,您也可以将 HTTPS 协议用作身份验证的基础,在某些情况下,这更容易配置。请参阅 第 3.1 节 “验证方案”。
设置身份验证的步骤
在概述中,您需要执行以下步骤来设置应用程序以使用身份验证:
- 将支持令牌策略添加到 WSDL 合同中的端点。这会要求端点在其请求消息中包含特定类型的令牌(客户端凭证)。
- 在客户端,通过配置 Blueprint XML 中的相关端点来提供要发送的凭证。
- (可选) 在客户端上,如果您决定使用回调处理程序提供密码,请在 Java 中实施回调处理程序。
- 在服务器端,将回调处理器类与 Blueprint XML 中的端点关联。然后,回调处理程序负责对从远程客户端接收的凭据进行身份验证。
7.2. 指定身份验证策略
概述
如果您希望端点支持身份验证,请将 支持令牌策略与相关 的端点绑定相关联。支持令牌策略断言有几种不同类型的支持令牌策略,其中的元素的名称为 *SupportingTokens
(如 SupportingTokens
、SignedSupportingTokens
等)。有关完整列表,请参阅 “SupportingTokens assertions”一节。
将支持的令牌断言与端点关联有以下影响:
-
需要端点的消息包括指定的令牌类型(其中令牌方向由
sp:IncludeToken
属性指定)。 - 根据您使用的支持令牌元素的特定类型的,端点可能需要签名和/或加密令牌。
支持的令牌断言表示运行时会检查这些要求是否已被验证。但是 WS-SecurityPolicy 策略 不会 定义为运行时提供凭据的机制。您必须使用 Blueprint XML 配置来指定凭证(请参阅 第 7.3 节 “提供客户端凭证”)。
语法
*
元素(即,支持Tokens 后缀的所有元素)都使用以下语法: “SupportingTokens assertions”一节
SupportingTokens
<sp:SupportingTokensElement xmlns:sp="..." ... > <wsp:Policy xmlns:wsp="..."> [Token Assertion]+ <sp:AlgorithmSuite ... > ... </sp:AlgorithmSuite> ? ( <sp:SignedParts ... > ... </sp:SignedParts> | <sp:SignedElements ... > ... </sp:SignedElements> | <sp:EncryptedParts ... > ... </sp:EncryptedParts> | <sp:EncryptedElements ... > ... </sp:EncryptedElements> | ) * ... </wsp:Policy> ... </sp:SupportingTokensElement>
如果 SupportingTokensElement 代表一个支持令牌元素,则 *支持Tokens
.Typly .Typly 需要在安全标头中包含令牌(或令牌),您可以在策略中包含一个或多个令牌断言,[Token Assertion]
。特别是,这是身份验证需要的所有。
如果令牌是适当类型(例如,X.509 证书或对称密钥),您可以理论上使用它使用它为其使用 sp:AlgorithmSuite
、sp:SignedParts
、sp:SignedPartments、sp:Signed
Partments
、sp 和加密
当前消息的特定部分。但是,Apache CXF 目前不支持 此功能。
策略示例
例 7.1 “支持问题单中的令牌策略示例” 显示需要在安全标头中包含 WS-Security UsernameToken 令牌(包含用户名/密码凭证)的策略示例。另外,因为令牌是在 sp:SignedSupportingTokens
元素内指定的,所以该策略需要签名该令牌。这个示例使用传输绑定,因此它是负责签署消息的底层传输。
例如,如果底层传输是 HTTPS,则 SSL/TLS 协议(配置了适当的算法套件)负责 对整个 消息签名,包括包含指定令牌的安全标头。这足以满足支持令牌签名的要求。
例 7.1. 支持问题单中的令牌策略示例
<wsp:Policy wsu:Id="UserNameOverTransport_IPingService_policy"> <wsp:ExactlyOne> <wsp:All> <sp:TransportBinding> ... </sp:TransportBinding> <sp:SignedSupportingTokens xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"> <wsp:Policy> <sp:UsernameToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient"> <wsp:Policy> <sp:WssUsernameToken10/> </wsp:Policy> </sp:UsernameToken> </wsp:Policy> </sp:SignedSupportingTokens> ... </wsp:All> </wsp:ExactlyOne> </wsp:Policy>
其中存在 sp:WssUsernameToken10
子元素表示 UsernameToken 标头应当符合 WS-Security UsernameToken 规格的版本 1.0。
令牌类型
在原则上,您可以在支持的令牌中指定 WS-SecurityPolicy 令牌类型。但是,对于 SOAP 级身份验证,只有 sp:UsernameToken
令牌类型相关。
sp:UsernameToken
在支持令牌断言的情况下,此元素指定在安全 SOAP 标头中包含 WS-Security UsernameToken。本质上讲,WS-Security UsernameToken 用于在 WS-Security SOAP 标头中发送用户名/密码凭证。sp:UsernameToken
元素使用以下语法:
<sp:UsernameToken sp:IncludeToken="xs:anyURI"? xmlns:sp="..." ... > ( <sp:Issuer>wsa:EndpointReferenceType</sp:Issuer> | <sp:IssuerName>xs:anyURI</sp:IssuerName> ) ? <wst:Claims Dialect="..."> ... </wst:Claims> ? <wsp:Policy xmlns:wsp="..."> ( <sp:NoPassword ... /> | <sp:HashPassword ... /> ) ? ( <sp:RequireDerivedKeys /> | <sp:RequireImpliedDerivedKeys ... /> | <sp:RequireExplicitDerivedKeys ... /> ) ? ( <sp:WssUsernameToken10 ... /> | <sp:WssUsernameToken11 ... /> ) ? ... </wsp:Policy> ... </sp:UsernameToken>
sp:UsernameToken
的子元素都是可选的,普通身份验证不需要它们。通常,与此语法中唯一相关的部分是 sp:IncludeToken
属性。
目前,在 sp:UsernameToken
语法中,Apache CXF 仅支持 sp:WssUsernameToken10
子元素。
sp:IncludeToken attribute
sp:IncludeToken
的值必须与保护策略中的 WS-SecurityPolicy 版本匹配。当前版本是 1.2,但旧的 WSDL 可能使用版本 1.1。sp:IncludeToken
属性的有效值如下:
- Never
令牌 MUST 不包含在发起方和接收方之间发送的任何消息;而应使用对令牌的外部引用。有效 URI 值是:
- once
令牌 MUST 仅包含在从启动器发送到接收者的一个消息中。引用令牌 MAY 使用内部参考机制。在接收者和发起方之间发送的后续相关消息可能会使用外部参考机制来引用令牌。有效 URI 值是:
- AlwaysToRecipient
令牌 MUST 包含在从启动器发送到接收者的所有消息中。令牌 MUST 不包含在从接收者发送到启动器的信息中。有效 URI 值是:
- AlwaysToInitiator
令牌 MUST 包含在从接收者发送到启动器的所有消息中。令牌 MUST 不包含在从启动器发送到接收者的信息中。有效 URI 值是:
- Always
令牌 MUST 包含在发起方和接收方之间的所有消息中。这是默认的行为。有效 URI 值是:
SupportingTokens assertions
支持以下支持令牌断言:
sp:SupportingTokens
此元素要求指定类型的令牌(或令牌)包含在 wsse:Security
标头中。没有应用额外的要求。
此策略未明确要求对令牌进行签名或加密。但是,通常而言,通过签名和加密来保护令牌。
sp:SignedSupportingTokens
此元素要求指定类型的令牌(或令牌)包含在 wsse:Security
标头中。此外,此策略还要求对令牌进行签名,以保证令牌的完整性。
此策略不明确要求对令牌进行加密。但是,通常而言,通过签名和加密来保护令牌。
sp:EncryptedSupportingTokens
此元素要求指定类型的令牌(或令牌)包含在 wsse:Security
标头中。此外,此策略还要求令牌加密,以便保证令牌机密性。
此策略未明确要求对令牌进行签名。但是,通常而言,通过签名和加密来保护令牌。
sp:SignedEncryptedSupportingTokens
此元素要求指定类型的令牌(或令牌)包含在 wsse:Security
标头中。此外,此策略还要求令牌签名和加密,以保证令牌完整性和机密性。
sp:EndorsingSupportingTokens
支持令牌的终止者用于签署邮件签名(主要签名)。这个签名被称为 签名 或 二级签名。因此,通过应用支持令牌策略,您可以有一个签名链:主签名(签署消息本身)和次要签名(为主签名签名签名)。
如果您使用传输绑定(例如 HTTPS),则消息签名实际上不属于 SOAP 信息,因此在这种情况下无法签署消息签名。如果您使用传输绑定指定这个策略,则声明令牌会改为为时间戳签名。
此策略未明确要求对令牌进行签名或加密。但是,通常而言,通过签名和加密来保护令牌。
sp:SignedEndorsingSupportingTokens
这个策略与支持令牌策略的声明相同,除了令牌需要签名才能保证令牌的完整性。
此策略不明确要求对令牌进行加密。但是,通常而言,通过签名和加密来保护令牌。
sp:EndorsingEncryptedSupportingTokens
这个策略与支持令牌策略的声明相同,除了需要加密令牌才能保证令牌保密性。
此策略未明确要求对令牌进行签名。但是,通常而言,通过签名和加密来保护令牌。
sp:SignedEndorsingEncryptedSupportingTokens
这个策略与支持令牌策略的声明相同,除了令牌需要签名和加密才能保证令牌的完整性和保密性。
7.3. 提供客户端凭证
概述
提供 UsernameToken
客户端凭证基本上有两种方法:您可以在客户端的 Blueprint XML 配置中直接设置用户名和密码;或者,您可以在客户端配置中设置用户名并实施回调处理程序以以编程方式提供密码。后一种方法(通过编程)可以方便密码在视图中显示。
客户端凭证属性
表 7.1 “客户端凭证属性” 显示在 Blueprint XML 中客户端请求上下文上指定 WS-Security username/password 凭据的属性。
表 7.1. 客户端凭证属性
Properties | 描述 |
---|---|
| 指定 UsernameToken policy assertions 的用户名。 |
| 指定 UsernameToken policy assertions 的密码。如果未指定,则可通过调用回调处理程序来获取密码。 |
| 指定 WSS4J 回调处理器的类名称,用于检索 UsernameToken 策略断言的密码。请注意,回调处理器也可以处理其他类型的安全事件。 |
在 Blueprint XML 中配置客户端凭证
要在 Blueprint XML 中客户端请求上下文中配置用户名/密码凭证,请按如下所示设置 security.username
和 security.password
属性:
<beans ... > <jaxws:client name="{NamespaceName}LocalPortName" createdFromAPI="true"> <jaxws:properties> <entry key="security.username" value="Alice"/> <entry key="security.password" value="abcd!1234"/> </jaxws:properties> </jaxws:client> ... </beans>
如果您不希望直接在 Blueprint XML 中存储密码(这可能是安全风险),您可以使用回调处理程序提供密码。
为密码编程回调处理器
如果要使用回调处理器为 UsernameToken 标头提供密码,您必须首先修改 Blueprint XML 中的客户端配置,将 security
.callback-handler 设置替换为 security.callback-handler
设置,如下所示:
<beans ... > <jaxws:client name="{NamespaceName}LocalPortName" createdFromAPI="true"> <jaxws:properties> <entry key="security.username" value="Alice"/> <entry key="security.callback-handler" value="interop.client.UTPasswordCallback"/> </jaxws:properties> </jaxws:client> ... </beans>
在前面的示例中,回调处理程序由 UT PasswordCallback 类实施
。您可以通过实施 javax.security.auth.callback.CallbackHandler
接口来编写回调处理程序,如 例 7.2 “UsernameToken 密码的回调处理程序” 所示。
例 7.2. UsernameToken 密码的回调处理程序
package interop.client;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class UTPasswordCallback implements CallbackHandler {
private Map<String, String> passwords =
new HashMap<String, String>();
public UTPasswordCallback() {
passwords.put("Alice", "ecilA");
passwords.put("Frank", "invalid-password");
//for MS clients
passwords.put("abcd", "dcba");
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
String pass = passwords.get(pc.getIdentifier());
if (pass != null) {
pc.setPassword(pass);
return;
}
}
throw new IOException();
}
// Add an alias/password pair to the callback mechanism.
public void setAliasPassword(String alias, String password) {
passwords.put(alias, password);
}
}
回调功能通过 CallbackHandler.handle()
方法实施。在本例中,假设传递给 handle()
方法的回调对象是 org.apache.ws.security.WSPasswordCallback 类型(在更现实示例中,您将检查回调对象的类型)。
客户端回调处理器的更真实的实施可能由提示用户输入其密码组成。
WSPasswordCallback 类
在 Apache CXF 客户端中调用一个 回调处理程序
时,用于设置 UsernameToken
密码的目的,对应的 WSPasswordCallback
对象具有 USERNAME_TOKEN
使用代码。
有关 WSPasswordCallback
类的更多详情,请参阅 org.apache.ws.security.WSPasswordCallback。
WSPasswordCallback
类定义了几种不同的使用代码,如下所示:
- USERNAME_TOKEN
获取 UsernameToken 凭证的密码。该使用代码在客户端(用于获取发送到服务器的密码之间)和服务器端(获取密码)与客户端接收的密码进行比较。
在服务器端,在以下情况下设置这个代码:
-
摘要密码- 如果 UsernameToken 包含摘要密码,则回调必须为给定用户名返回对应的密码(given by
WSPasswordCallback.getIdentifier()
)。验证密码(与摘要密码进行比较)由 WSS4J 运行时完成。 - 纯文本密码- 实施与摘要密码相同的方法(自 Apache CXF 2.4.0 开始)。
自定义密码类型- 如果
getHandleCustomPasswordTypes()
在org.apache.ws.security.WSSConfig
上为true
,则此例的实施方式与摘要密码问题单相同(自 Apache CXF 2.4.0 开始。否则,会抛出异常。如果服务器端的已接收 UsernameToken 中没有包括
Password
元素,则回调处理程序不会被调用(自 Apache CXF 2.4.0 起)。
-
摘要密码- 如果 UsernameToken 包含摘要密码,则回调必须为给定用户名返回对应的密码(given by
- DECRYPT
-
需要密码从 Java 密钥存储检索私钥,其中
WSPasswordCallback.getIdentifier()
提供密钥存储条目的别名。WSS4J 使用这个私钥解密会话(symmetric)密钥。 - 签名
-
需要密码从 Java 密钥存储检索私钥,其中
WSPasswordCallback.getIdentifier()
提供密钥存储条目的别名。WSS4J 使用此私钥生成签名。 - SECRET_KEY
-
需要密钥进行加密或签名,或者在入站端进行解密或验证。回调处理程序必须使用
setKey(byte[])
方法设置密钥。 - SECURITY_CONTEXT_TOKEN
-
需要
wsc:SecurityContextToken
的密钥,通过调用setKey(byte[])
方法提供它。 - CUSTOM_TOKEN
-
需要令牌作为 DOM 元素。例如,这用于对不在消息中的 SAML Assertion 或 SecurityContextToken 的引用。回调处理程序必须使用
setCustomToken(Element)
方法设置令牌。 - KEY_NAME
- (过时的) Since Apache CXF 2.4.0,这个使用代码已过时。
- USERNAME_TOKEN_UNKNOWN
- (过时的) Since Apache CXF 2.4.0,这个使用代码已过时。
- UNKNOWN
- WSS4J 未使用。
7.4. 验证接收的凭证
概述
在服务器端,您可以通过使用 Apache CXF 运行时注册回调处理器来验证收到的凭证是否是身份验证。您可以自行编写自定义代码来执行凭据验证,也可以实施与第三方企业安全系统(如 LDAP 服务器)集成的回调处理器。
在 Blueprint XML 中配置服务器回调处理器
要配置服务器回调处理程序,以验证从客户端接收的 UsernameToken
凭据,请在服务器的 Blueprint XML 配置中设置 security.callback-handler
属性,如下所示:
<beans ... > <jaxws:endpoint id="UserNameOverTransport" address="https://localhost:9001/UserNameOverTransport" serviceName="interop:PingService10" endpointName="interop:UserNameOverTransport_IPingService" implementor="interop.server.UserNameOverTransport" depends-on="tls-settings"> <jaxws:properties> <entry key="security.username" value="Alice"/> <entry key="security.callback-handler" value="interop.client.UTPasswordCallback"/> </jaxws:properties> </jaxws:endpoint> ... </beans>
在前面的示例中,回调处理程序由 UT PasswordCallback 类实施
。
实施回调处理器以检查密码
要实现用于检查服务器端的回调处理程序,请实施 javax.security.auth.callback.CallbackHandler
接口。为服务器实施 回调处理程序
接口的一般方法与为客户端实施 回调处理程序
类似。给服务器端返回的密码的解释有所不同,但是:将来自回调处理器的密码与接收的客户端密码进行比较,以验证客户端的凭据。
例如,您可以使用 例 7.2 “UsernameToken 密码的回调处理程序” 中显示的示例实现来获取服务器端的密码。在服务器端,WSS4J 运行时将从回调中获取的密码与接收客户端凭据中的密码进行比较。如果两个密码匹配,则成功验证凭据。
对服务器回调处理程序的更真实的实现将涉及编写与用于存储安全数据的第三方数据库的集成(例如,与 LDAP 服务器集成)。
第 8 章 Fuse 凭证存储
8.1. 概述
Fuse 凭据存储功能可以将密码和其他敏感字符串包含在内。这些字符串通过 JBoss EAP Elytron 凭据存储 来解决。
凭据存储对 OSGI 环境进行了内置支持,专门用于 Apache Karaf 和 Java 系统属性。
您可能已经指定了密码,如 javax.net.ssl.keyStorePassword
,作为系统属性(在明文中)可让您将这些值指定为凭证存储的引用。
Fuse Credential Store 允许将敏感字符串指定为对存储在凭据存储中的值的引用。clear text 值被替换为别名参考,例如 CS:alias
引用配置的 Credential Store 中 别名
下存储的值。
约定 CS:alias
应该遵循。CS:
在 Java System 属性值中,它将用于查找值的前缀和 别名
。
8.2. 先决条件
- Karaf 容器正在运行。
8.3. 在 Karaf 上设置 Fuse Credential Store
使用
credential-store:create
命令创建凭证存储:karaf@root()> credential-store:create -a location=credential.store -k password="my password" -k algorithm=masked-MD5-DES In order to use this credential store set the following environment variables Variable | Value ------------------------------------------------------------------------------------------------------------------------ CREDENTIAL_STORE_PROTECTION_ALGORITHM | masked-MD5-DES CREDENTIAL_STORE_PROTECTION_PARAMS | MDkEKXNvbWVhcmJpdHJhcnljcmF6eXN0cmluZ3RoYXRkb2Vzbm90bWF0dGVyAgID6AQIsUOEqvog6XI= CREDENTIAL_STORE_PROTECTION | Sf6sYy7gNpygs311zcQh8Q== CREDENTIAL_STORE_ATTR_location | credential.store Or simply use this: export CREDENTIAL_STORE_PROTECTION_ALGORITHM=masked-MD5-DES export CREDENTIAL_STORE_PROTECTION_PARAMS=MDkEKXNvbWVhcmJpdHJhcnljcmF6eXN0cmluZ3RoYXRkb2Vzbm90bWF0dGVyAgID6AQIsUOEqvog6XI= export CREDENTIAL_STORE_PROTECTION=Sf6sYy7gNpygs311zcQh8Q== export CREDENTIAL_STORE_ATTR_location=credential.store
这应该是
用于存储
secret 的 JCEKS KeyStore 文件。退出 Karaf 容器:
karaf@root()> logout
设置创建凭证存储时显示的环境变量:
$ export CREDENTIAL_STORE_PROTECTION_ALGORITHM=masked-MD5-DES $ export CREDENTIAL_STORE_PROTECTION_PARAMS=MDkEKXNvbWVhcmJpdHJhcnljcmF6eXN0cmluZ3RoYXRkb2Vzbm90bWF0dGVyAgID6AQIsUOEqvog6XI= $ export CREDENTIAL_STORE_PROTECTION=Sf6sYy7gNpygs311zcQh8Q== $ export CREDENTIAL_STORE_ATTR_location=credential.store
重要在启动 Karaf 容器前,您需要先设置
CREDENTIAL_STORE_*
环境变量。启动 Karaf 容器:
bin/karaf
使用
credential-store:store
将 secret 添加到凭证存储中:karaf@root()> credential-store:store -a javax.net.ssl.keyStorePassword -s "alias is set" Value stored in the credential store to reference it use: CS:javax.net.ssl.keyStorePassword
再次退出 Karaf 容器:
karaf@root()> logout
再次运行 Karaf 容器,指定对 secret 的引用,而不是值:
$ EXTRA_JAVA_OPTS="-Djavax.net.ssl.keyStorePassword=CS:javax.net.ssl.keyStorePassword" bin/karaf
当使用 System::getProperty
访问时,javax.net.ssl.keyStorePassword
的值应包含字符串 "alias is set"
。
EXTRA_JAVA_OPTS
是很多方法指定系统属性。这些系统属性在 Karaf 容器开始时定义。
当环境变量在您的环境中泄漏或预期与凭据存储文件的内容一起使用时,您的机密会被破坏。当通过 JMX 访问时,属性的值替换为字符串 "& lt;sensitive>"
,但有很多代码路径会导致 System::getProperty
,用于实例诊断或监控工具可能会访问它以调试目的。
附录 A. ASN.1 和可辨识名称
摘要
OSI Abstract 语法 Notation One(ASN.1)和 X.500 Distinguished Names 在定义 X.509 证书和密钥 LDAP 目录的安全标准中发挥了重要作用。
A.1. ASN.1
概述
Abstract 语法 Notation One (ASN.1)在 1980 年早期由 OSI 标准正文定义,以提供独立于任何特定机器硬件或编程语言的数据类型和结构的方法。在很多方面,ASN.1 可以被视为现代接口定义语言的runner,如 OMG 的 IDL 和 WSDL,后者与定义平台相关的数据类型相关。
ASN.1 很重要,因为它在标准定义中广泛使用(如 SNMP、X.509 和 LDAP)。特别是 ASN.1 在安全标准字段中都无处不在。X.509 证书的正式定义和可区分名称使用 ASN.1 语法描述。您不需要详细了解 ASN.1 语法以使用这些安全标准,但您需要注意 ASN.1 用于大多数安全相关数据类型的基本定义。
BER
OSI 的基本编码规则(BER)定义如何将 ASN.1 数据类型转换为一系列 octets(二进制表示)。因此,对于 ASN.1 的 BER 扮演的角色是:GIOP 与 GIOP 对 OMG IDL 的作用类似。
DER
OSI 的可辨识规则(DER)是 BER 的分类。DER 由 BER 加上一些额外的规则来确保编码是唯一的(BER 编码不是)。
参考信息
您可以在以下标准文件中了解更多有关 ASN.1 的信息:
- ASN.1 在 X.208 中定义。
- BER 在 X.209 中定义。
A.2. 区分名称
概述
过去,可分辨名称(DN)定义为 X.500 目录结构中的主键。但是,在很多其他上下文中必须使用 DN 作为常规用途标识符。在 Apache CXF 中,在以下情况下进行 DN:
- X.509 证书(例如,证书中的 DN)用于标识证书的所有者(安全主体)。
- LDAP-DN 用于查找 LDAP 目录树中的对象。
DN 的字符串表示
虽然 DN 在 ASN.1 中正式定义,但也有一个 LDAP 标准来定义 DN 的 UTF-8 字符串表示(请参阅 RFC 2253
)。字符串表示为描述 DN 结构提供了便捷的基础。
DN 的字符串表示法 不提供对 DER 编码的 DN 的唯一表示。因此,从字符串格式转换为 DER 格式的 DN 并不总是恢复原始 DER 编码。
DN 字符串示例
以下字符串是 DN 的典型示例:
C=US,O=IONA Technologies,OU=Engineering,CN=A. N. Other
DN 字符串的结构
从以下基本元素构建 DN 字符串:
OID
属性类型
在 DN 中可以出现的各种属性类型是理论上打开的,但在实践中只能使用少量属性类型。表 A.1 “常用属性类型” 显示您最有可能遇到的属性类型:
表 A.1. 常用属性类型
字符串代表 | X.500 属性类型 |
---|---|
数据的大小 | 等效的 OID |
C | countryName |
2 | 2.5.4.6 |
O | organizationName |
1…64 | 2.5.4.10 |
OU | organizationalUnitName |
1…64 | 2.5.4.11 |
CN | commonName |
1…64 | 2.5.4.3 |
ST | stateOrProvinceName |
1…64 | 2.5.4.8 |
L | localityName |
1…64 | 2.5.4.7 |
STREET | streetAddress |
DC | domainComponent |
UID | userid |
AVA
属性值断言 (AVA)为属性类型分配属性值。在字符串表示中,它使用以下语法:
<attr-type>=<attr-value>
例如:
CN=A. N. Other
或者,您可以使用等同的 OID 标识字符串表示中的属性类型(请参阅 表 A.1 “常用属性类型” )。例如:
2.5.4.3=A. N. Other
RDN
相对可分名称 (RDN)代表 DN 的单个节点(字符串表示中逗号之间的位)。从技术上讲,RDN 可能包含多个 AVA(它被正式定义为一组 AVA)。但是,在实践中几乎不会发生。在字符串表示中,RDN 具有以下语法:
<attr-type>=<attr-value>[+<attr-type>=<attr-value> ...]
下面是一个(不太可能)多值 RDN 的示例:
OU=Eng1+OU=Eng2+OU=Eng3
以下是单值 RDN 的示例:
OU=Engineering