第 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 证书:

注意

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-If true (默认值),服务器请求客户端在 TLS 握手期间显示 X.509 证书; 如果为,则服务器 不会 请求客户端提供 X.509 证书。
  • 必需的 attribute-If true,如果客户端在 TLS 握手中无法显示 X.509 证书,则服务器会引发异常;如果客户端未能显示 X.509 证书,则服务器 不会 引发异常。