尽管将“disableCNCheck”设置为true,但https URL主机名与公共名称(CN)不匹配

时间:2014-01-14 17:41:52

标签: java web-services ssl https cxf

我设法正确配置了基于CXF的客户端,以便为运行Web服务的服务器找到正确的SSL证书:

  <http:conduit name="https://myserver/myws/register/soap?wsdl:{http://glob.reg.com/myws}.http-conduit">

    <http:tlsClientParameters>
      <sec:keyManagers keyPassword="changeit">
        <sec:keyStore type="JKS" password="changeit"
                  file="C:\Program Files (x86)\Java\jdk1.6.0_45\jre\lib\security\cacerts"/> 
       </sec:keyManagers>
      <sec:trustManagers>
        <sec:keyStore type="JKS" password="changeit"
                  file="C:\Program Files (x86)\Java\jdk1.6.0_45\jre\lib\security\cacerts"/> 
      </sec:trustManagers>
      <sec:cipherSuitesFilter>
        <!-- these filters ensure that a ciphersuite with
             export-suitable or null encryption is used,
             but exclude anonymous Diffie-Hellman key change as
             this is vulnerable to man-in-the-middle attacks -->
        <sec:include>.*_EXPORT_.*</sec:include>
        <sec:include>.*_EXPORT1024_.*</sec:include>
        <sec:include>.*_WITH_DES_.*</sec:include>
        <sec:include>.*_WITH_AES_.*</sec:include>
        <sec:include>.*_WITH_NULL_.*</sec:include>
        <sec:exclude>.*_DH_anon_.*</sec:exclude>
      </sec:cipherSuitesFilter>
    </http:tlsClientParameters>
    <http:authorization>
      <sec:UserName>Betty</sec:UserName>
      <sec:Password>password</sec:Password>
    </http:authorization>
    <http:client AutoRedirect="true" Connection="Keep-Alive"/>

  </http:conduit>

但是......因为证书是针对与我服务器的机器不同的子域名(映射到相同的IP地址),我收到以下错误:

Caused by: java.io.IOException: The https URL hostname does not match the Common Name (CN) on the server certificate in the client's truststore.  Make sure serv
er certificate is correct, or to disable this check (NOT recommended for production) set the CXF client TLS configuration property "disableCNCheck" to true.
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1234)
        at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.onFirstWrite(URLConnectionHTTPConduit.java:183)
        at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
        at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1293)
        ... 18 more

所以...... 因为这是一个开发/测试系统,我就像所提出的消息一样(将CXF客户端TLS配置属性“disableCNCheck”设置为true):

<http:tlsClientParameters disableCNCheck="true">

加号,我将以下代码添加到客户的主类(根据建议in this thread):

  static {
    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier()
    {
      @Override
      public boolean verify(String hostname, SSLSession session)
      {
        return true;
      }

    });    
  }

但是...... 我仍然遇到同样的错误:

Caused by: java.io.IOException: The https URL hostname does not match the Common Name (CN) on the server certificate in the client's truststore.  Make sure serv
er certificate is correct, or to disable this check (NOT recommended for production) set the CXF client TLS configuration property "disableCNCheck" to true.
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1234)
        at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.onFirstWrite(URLConnectionHTTPConduit.java:183)
        at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
        at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69)
        at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1293)
        ... 18 more

知道为什么吗?

我的意思是,上述解决方法之一应该足以让客户端忽略证书URL不匹配,但在我的情况下,既不起作用也不起作用

为什么?

5 个答案:

答案 0 :(得分:8)

我在几个

的情况下使用了CXF
<http:tlsClientParameters disableCNCheck="true">

足以禁用CN检查。

您确定您的客户正在使用该管道配置吗?我的理解是管道名称模式需要以某种方式匹配端点URI。

尝试按如下方式设置管道名称,以便任何端点匹配并查看是否有任何改变:

<http:conduit name="*.http-conduit">

2015年1月2日更新

事实证明,http-conduit配置名称匹配有两种模式格式。一个涉及服务的命名空间和端口名称。另一种受支持的格式是与用于创建客户端的WSDL中指定的URL端点匹配的正则表达式。

引用Apache CXF User Guide关于http-conduit元素:

  

该名称包含服务的名称空间,WSDL端口名称(如   在WSDL的wsdl:service部分找到,和“.http-conduit”。   它遵循以下模板:

     

{WSDL Namespace}portName.http-conduit

     

注意:它是PORT名称,而不是服务名称。

     

...

     

另一种选择   name属性是一个注册表达式(例如,“http://myserver.example.com:*”)   用于端点的ORIGINAL URL。配置匹配   管道创建所以在WSDL中使用的地址或用于   JAX-WS Service.create(...)调用可用于名称。

答案 1 :(得分:2)

-Djsse.enableSNIExtension=false放入您的appserver VM选项。

答案 2 :(得分:1)

添加以下代码以设置disableCNCheck

 HTTPConduit httpConduit=(HTTPConduit)ClientProxy.getClient(port).getConduit();
        TLSClientParameters tlsCP = new TLSClientParameters();
        tlsCP.setDisableCNCheck(true);
        httpConduit.setTlsClientParameters(tlsCP);

仅在较低的环境中使用此代码,不建议在较高的环境中使用。

答案 3 :(得分:0)

在调用 url 时使用主机的 FQDN 名称,因为它会尝试与证书中存在的名称匹配,并且通常仅使用 FQDN 生成证书。 因为 disableCNcheck 不是一个可取的方法。

答案 4 :(得分:0)

这个解决方案在使用 tomcat 运行时对我有用。创建一个禁用主机名验证的 jar 并将其作为 javaagent 传递给您的运行时容器。 https://stackoverflow.com/a/13032654/2815984