尝试从安全站点生成 Web 服务客户端时出现奇怪的证书错误
当尝试使用 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 时发生,并且仅针对此特定服务器。我有另一个具有相同设置的网络服务器,并且一切正常。我三次检查了所有密钥库,看起来所有 CA 证书都已正确加载。我尝试使用具有相同设置的另一台服务器,并且能够毫无问题地生成客户端代理代码。奇怪的是,如果我使用从其他服务器生成的代码来对抗奇怪的服务器,一切都会正常工作。只有 Wsdl2Java 给我带来了问题。
I get a weird error when trying to use AXIS1.4 Wsdl2Java tool to generate client code for the web service that is installed on the secure IIS site. When I run the tool I get the following SSL exception:
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)
Weird thing is that this error only occurs when I run WSDL2Java, and only for this particular server. I have another web server with the identical set-up and everything works fine there. I triple checked all the keystores and it looks like all the CA certificates are loaded correctly. I tried using another server with the identical setup, and was able to generate the client proxy code without any problems. Weird thing is that if I use the code generated from the other server against the weird server everything works fine. It is only Wsdl2Java that is giving me a problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
主机的 DNS 名称(例如 machine1.mydomain.tld)和证书中的
CommonName
值很可能不匹配,因此会出现CertificateException
。从这篇博客文章中:There is very likely a mismatch between the DNS name of the host (e.g. machine1.mydomain.tld) and the
CommonName
value from the certificate, hence theCertificateException
. From this blog post:您可能会发现使用 SSL 调试系统属性有助于调查此问题:
如果打印输出太多,您可以过滤一些内容,也许是这样:
输出不一定显而易见,但它应该告诉您错误在哪里是更详细的。
You may find using the SSL debugging system properties can be helpful to investigate this problem:
If there's too much printed out, you can filter some things, perhaps this:
The output is not necessarily obvious to read, but it should tell you where the error is in more detail.
问题是 WSDL2Java 由于名称而拒绝了服务器证书。在 Java 中,用于连接到远程系统的主机名与证书中的通用名称非常匹配。它不会根据 IP 地址进行反向查找。您必须使用主机名进行连接。
其他回复表明您正在通过 IP 地址进行连接。这不是正确的做事方式。 Java 将根据其连接的主机名验证证书。
如果您使用 IP 地址进行连接,您的环境中可能没有设置 DNS。解决此问题的最简单方法是将主机名添加到主机文件中。在 Windows 中,它位于“C:\Windows\System32\drivers\etc\hosts”。
这将允许您使用主机名通过 WSDL2Java 获取 WSDL。
替代方案:
如果仍然不起作用,还有一个替代方案。使用 Web 浏览器下载 .wsdl 文件。让 WSDL2Java 从磁盘上的本地文件而不是 Web 服务器上创建 Java 存根。生成的代码将是相同的,但不必通过 SSL 来获取 WSDL。
The problem is that WSDL2Java has rejected the Server certificate because of name. In Java, the hostname you use to connect to the remote system much match the common name in the certificate. It will not reverse lookup based on the IP Address. You must connect using the hostname.
Other replies indicated that you are connecting via the IP Address. This is not the correct way to do things. Java will validate the certificate against the hostname it is connecting to.
If you are connecting using the IP Address you might not have DNS set up in your environment. The easiest way to get around this is to add the hostname to your hosts file. In windows this is located in 'C:\Windows\System32\drivers\etc\hosts'.
This will allow you to use the hostname to get the WSDL through WSDL2Java.
Alternative:
There is an alternative if that still does not work. Download the .wsdl file using your web browser. Have WSDL2Java create your Java stubs from the local file on disk instead of on the web server. The code generated will be identical but it will not have to go through SSL to get the WSDL.
如果您手头有服务器证书并安装了 openssl,您可以使用以下内容转储证书的内容:
您将看到“CN =”作为主题的一部分,如果它在证书中具有 altSubjectName 扩展名,则您'您将在下面的 X509v3 扩展下看到它,作为 X509v3 主题备用名称,并且您将在此处查找类似 DNS:host-name- 的内容。
如果它与您要连接的主机名匹配,则只需检查您在通过的任何 SSL 接口中是否通过 IP 地址或主机名进行连接,并确保它是通过主机名而不是 IP 地址进行连接。
如果证书中没有匹配的名称(与您要连接的主机名匹配),某些 SSL 接口会让您忽略“名称不匹配”。 (我不知道在您的具体情况下如何执行此操作。)
编辑:
尝试通过主机名而不是 IP 地址进行连接,看看是否有差异。
如果证书中列出了 IP,您将在 openssl 输出中的 X509v3 使用者备用名称下看到类似 IP:xx.xx.xx.xx 的内容。
如果未列出 IP,请从 shell 提示符运行 nslookup 并比较工作服务器地址和非工作服务器地址的输出。这可能是工作服务器匹配主机名的方式(即通过 getnetbyaddr 的方式)。
编辑2:
您是否尝试过通过主机名(在连接字符串中)进行连接,但仍然遇到相同的错误?使用 IP 地址通过浏览器连接是否有效并不重要——浏览器可能不会使用相同的算法来验证主机名。您是否尝试过使用连接中的 IP 地址连接到良好的服务器?另外,请在此处查找可尝试的内容:发现于快速谷歌
If you have the server certificate at hand and openssl installed you can dump the contents of the certificate with something like:
You'll see "CN=" as part of the Subject, and if it has the altSubjectName extension in the certificate, you'll see that below under X509v3 extensions, as X509v3 Subject Alternative Name, and you'll be looking for something like DNS:host-name-here.
If that matches the hostname you are connecting to, then just check if you are connecting by IP address, or by hostname, in whatever SSL interface you go through, and make sure it is by hostname and not by IP address.
If there is no matching name in the certificate (that matches the hostname you are connecting to), some SSL interfaces will let you ignore the "name mismatch". (I don't know how to do that in your specific case.)
EDIT:
Try connecting by hostname instead of IP address and see if there is a difference.
If the IP is listed in the certificate, you'll see something like IP:xx.xx.xx.xx under X509v3 Subject Alternative Name in the openssl output.
If the IP is not listed, run nslookup from a shell prompt and compare the output for both the working and non-working server addresses. This may be how the working server is matching the hostname (i.e. by way of getnetbyaddr).
EDIT 2:
Have you tried connecting by hostname (in your connect string) and still get the same error? It doesn't matter if connecting via browser using the IP address works -- the browser may not be verifying the hostname using the same algorithm. Have you tried connecting to the good server using an IP address in the connect? Also, look here for something to try: found with quick Google
您是否缺少适当的 Java 的 GlobalSign 根证书。
另一种可能性涉及根证书和中间证书的组合。来自 GlobalSign 网站 的更多信息:
Could it be that you are missing the appropriate GlobalSign root certificate for Java.
Another possibility relates to the combination of the root and intermediate certificate. More from the GlobalSign website: