前段时间尝试在自己本机访问https 资源,一直困于“No subject alternative names present”这个错误。

Exception in thread "main" javax.xml.ws.WebServiceException: Failed to access the WSDL at: https://IP:8443/security/2.0?wsdl. It failed with:

java.security.cert.CertificateException: No subject alternative names present.

      at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:151)

      at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:133)

      at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:254)

      at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:217)

      at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:165)

      at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:93)

      at javax.xml.ws.Service.<init>(Service.java:56)

因为之前项目吃紧,只好在公司已经配置好的平台上开发,把这个问题搁置了下来。随着第一个版本的成功发布,得了些空闲时间再次来研究这个问题。

从这篇文章中得到启示:http://www.coderanch.com/t/523511/sockets/java/Certificate-No-subject-alternative-names

I read that the problem usually appears when the "cn" in the certificate does not match the address of the server.
The "CN" in my certificate is "PRESS44"
The server address that was given to me is an ip.
https://xxx.xxx.xxx.xxx:123

难道不能用IP地址,必须要用主机名?先查查服务器端的配置。找到服务器端的keystore 文件

/usr/java/jdk1.6.0_15/bin/keytool -list -v -keystore -list -v -keystore server.keystore

一查果然CN用的是主机名,复制过来替换原来URL的IP地址。先在测试的Java类里跑跑看,“No subject” 问题是过了,又报如下的错:

Exception in thread "main" javax.xml.ws.WebServiceException: Failed to access the WSDL at: https://hostname:8443/security/2.0?wsdl. It failed with:

      Server returned HTTP response code: 401 for URL: https://hostname:8443/security/2.0?wsdl.

      at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(RuntimeWSDLParser.java:151)

      at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(RuntimeWSDLParser.java:133)

      at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:254)

      at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:217)

      at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:165)

      at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:93)

      at javax.xml.ws.Service.<init>(Service.java:56)

访问WSDL也需要安全认证,真是麻烦啊!突然想起前段时间做调研时,JBoss里似乎可以设置一个叫 ignoreHttpsHost 的参数。反正最后也要部署到JBoss,不妨就试试看,设置好三个参数:

System.setProperty("javax.net.ssl.trustStore", "C:\\test\\jssecacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
System.setProperty("org.jboss.security.ignoreHttpsHost", "true");

启动JBoss,跑SoapUI测试用例,三秒之后,成功返回结果。