https URL主机名与公用名(CN)不匹配,尽管设置了'disableCNCheck'真实



我设法正确配置了基于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)Javajdk1.6.0_45jrelibsecuritycacerts"/> 
</sec:keyManagers>
<sec:trustManagers>
<sec:keyStore type="JKS" password="changeit"
file="C:Program Files (x86)Javajdk1.6.0_45jrelibsecuritycacerts"/> 
</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">

另外,我将以下代码添加到我的客户的主类中(根据本线程中的建议):

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不匹配,但在我的情况下,既不起作用,也不起作用

为什么?

我在

<http:tlsClientParameters disableCNCheck="true">

足以禁用CN检查。

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

尝试按如下方式设置导管名称,使任何端点都匹配,并查看是否有任何变化:

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

2015年1月2日更新

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

引用有关http-conduit元素的Apache CXF用户指南:

名称包括服务的名称空间,WSDL端口名(作为在wsdl的wsdl:service部分中找到)和".http管道"。它遵循以下模板:

{WSDL Namespace}portName.http-conduit

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

的另一个选项name属性是reg ex表达式(例如http://myserver.example.com:*")用于端点的原始URL。配置匹配于管道创建,因此WSDL中使用的地址或JAX-WS Service.create(…)调用可以用于该名称。

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

添加以下代码以设置disableCNCheck

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

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

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

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

最新更新