第 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 证书。
-
使用 free
openssl
工具(可以从 http://www.openssl.org下载)和 Java密钥存储
实用程序来生成证书(请参阅 第 2.5.3 节 “使用 CA 在 Java Keystore 中创建签名证书”)。
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
元素的location
属性配置为使用 HTTPS URL。对于 SOAP 以外的绑定,您可以编辑http:address
元素的位置
属性中显示的 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
元素的 file
属性指定 Java 密钥存储文件 truststore.jks
,其中包含一个或多个可信 CA 证书。password
属性指定访问密钥存储( truststore.jks
)所需的密码。请参阅 第 3.2.2 节 “为 HTTPS 指定可信 CA 证书”。
您可以使用 resource
属性(密钥存储文件在 classpath 上提供)或 url
属性来指定密钥存储的位置。特别是,
resource
属性必须与部署到 OSGi 容器中的应用程序一起使用。您必须非常小心,不要从不可信源加载信任存储。
sec:cipherSuitesFilter
元素可用于缩小客户端用于 TLS 连接的密码套件选择范围。详情请查看 第 4 章 配置 HTTPS 加密套件。
使用证书的 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 Keystore 格式(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 Keystore 中创建签名证书”。
您可以使用 resource
属性(密钥存储文件在 classpath 上提供)或 url
属性来指定密钥存储的位置。特别是,
resource
属性必须与部署到 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 Keystore 格式(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 Keystore 中创建签名证书”。
sec:trustManagers
元素用于指定可信 CA 证书列表(服务器使用此列表来决定是否信任客户端提供的证书)。
sec:keyStore
元素的 file
属性指定 Java 密钥存储文件 truststore.jks
,其中包含一个或多个可信 CA 证书。password
属性指定访问密钥存储( truststore.jks
)所需的密码。请参阅 第 3.2.2 节 “为 HTTPS 指定可信 CA 证书”。
您可以使用 resource
属性或 url
属性指定密钥存储的位置,而不是指定 file
属性。
sec:cipherSuitesFilter
元素可用于缩小服务器用于 TLS 连接的密码套件选择范围。详情请查看 第 4 章 配置 HTTPS 加密套件。
sec:clientAuthentication
元素决定服务器对客户端证书的分布。元素具有以下属性:
-
want
attribute-Iftrue
(默认值),服务器请求客户端在 TLS 握手期间显示 X.509 证书;如果为
,则服务器 不会 请求客户端提供 X.509 证书。 -
必需的
attribute-Iftrue
,如果客户端在 TLS 握手中无法显示 X.509 证书,则服务器会引发异常;如果客户端未能显示 X.509 证书,则服务器 不会 引发异常。