尝试使用AXIS1.4 Wsdl2Java工具为安全IIS站点上安装的Web服务生成客户端代码时,出现了一个奇怪的错误。当我运行该工具时,我得到以下SSL异常:
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No
name matching XXXXXXX.net found
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1
591)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Clien
tHandshaker.java:975)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHa
ndshaker.java:123)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:5
16)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.jav
a:454)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.j
ava:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SS
LSocketImpl.java:1096)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketIm
pl.java:1123)
奇怪的是,这个错误只发生在我运行WSDL2Java时,并且只发生在这个特定的服务器上。我有另一个具有相同设置的Web服务器,一切正常。我对所有密钥库进行了三重检查,看起来所有CA证书都已正确加载。我尝试使用具有相同设置的另一台服务器,并且能够毫无问题地生成客户端代理代码。奇怪的是,如果我使用从其他服务器生成的代码对抗奇怪的服务器一切正常。只有Wsdl2Java给我一个问题。
答案 0 :(得分:1)
主机的DNS名称(例如machine1.mydomain.tld)与证书中的CommonName
值之间很可能不匹配,因此CertificateException
不匹配。从blog post:
- 如果您想通过使用IP作为主机名进行连接;
您的证书应该包含该ip值作为主题备用名称值(类型IPAddress:key = 7)。- 如果您想通过使用DNS作为主机名进行连接;
您的证书应该包含该DNS名称作为主题备用名称值(类型为DNS:key = 2)或作为CommonName(CN)值。
答案 1 :(得分:1)
您可能会发现使用SSL调试系统属性有助于调查此问题:
-Djavax.net.debug=ssl
如果打印得太多,你可以过滤一些东西,也许是这样:
-Djavax.net.debug=ssl,trustmanager
输出不一定非常明显,但它应该更详细地告诉您错误的位置。
答案 2 :(得分:0)
如果您手头有服务器证书并且安装了openssl,您可以使用以下内容转储证书的内容:
$ openssl x509 -noout -text -in filename-here.pem
你会看到“CN =”作为主题的一部分,如果它在证书中有altSubjectName扩展名,你会在X509v3扩展名下面看到,作为X509v3主题备用名称,你会看到对于类似DNS的东西:host-name-here。
如果匹配您要连接的主机名,那么只需检查您是通过IP地址连接,还是通过主机名连接,无论您使用何种SSL接口,都要确保它是通过主机名而不是IP地址。< / p>
如果证书中没有匹配的名称(与您要连接的主机名匹配),某些SSL接口将忽略“名称不匹配”。 (我不知道在你的具体情况下如何做到这一点。)
编辑:
尝试通过主机名而不是IP地址进行连接,看看是否存在差异。
如果证书中列出了IP,您将在openssl输出中的X509v3主题备用名称下看到类似IP:xx.xx.xx.xx的内容。
如果未列出IP,请从shell提示符运行nslookup,并比较工作和非工作服务器地址的输出。这可能是工作服务器与主机名匹配的方式(即通过getnetbyaddr)。
编辑2:
您是否尝试过使用主机名(在您的连接字符串中)进行连接并仍然得到相同的错误?使用IP地址通过浏览器连接无关紧要 - 浏览器可能无法使用相同的算法验证主机名。您是否尝试使用连接中的IP地址连接到良好的服务器?另外,请在此处查看:found with quick Google
答案 3 :(得分:0)
问题是WSDL2Java因名称而拒绝了服务器证书。在Java中,用于连接到远程系统的主机名与证书中的公用名非常匹配。它不会基于IP地址反向查找。您必须使用主机名进行连接。
其他回复表明您通过IP地址进行连接。这不是正确的做事方式。 Java将根据它连接的主机名验证证书。
如果使用IP地址进行连接,则可能未在您的环境中设置DNS。解决此问题的最简单方法是将主机名添加到hosts文件中。在Windows中,它位于'C:\ Windows \ System32 \ drivers \ etc \ hosts'。
xx.xx.xx.xx XXXXXXXXXX.net
这将允许您使用主机名通过WSDL2Java获取WSDL。
<强>替代:强>
如果仍然无效,还有另一种选择。使用Web浏览器下载.wsdl文件。让WSDL2Java从磁盘上的本地文件而不是Web服务器上创建Java存根。生成的代码将是相同的,但不必通过SSL来获取WSDL。
答案 4 :(得分:0)
可能是您错过了相应的GlobalSign root certificate for Java。
# Import a root or intermediate CA certificate to an existing Java keystore
keytool -import -trustcacerts -alias root -file Thawte.crt -keystore keystore.jks
另一种可能性涉及根证书和中间证书的组合。更多来自GlobalSign website:
“一些Apache和基于Java的 应用程序需要root和 中级证书 捆绑在一个证书中......“