背景:在開發一個項目中,要調用一個webservice服務,之前設置的是http協議,項目中采用jdk自帶的wsimport工具生成的客戶端代碼;
后來,需求變更要求兼容https協議的webservice,開始以為只需要簡單的將服務地址的連接改為https就可以了;但不行,總是報錯
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.tryWithMex(Unknown Source) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(Unknown Source) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(Unknown Source) at com.sun.xml.internal.ws.wsdl.parser.RuntimeWSDLParser.parse(Unknown Source) at com.sun.xml.internal.ws.client.WSServiceDelegate.parseWSDL(Unknown Source) at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(Unknown Source) at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(Unknown Source) at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(Unknown Source) at com.sun.xml.internal.ws.client.WSServiceDelegate.<init>(Unknown Source) at com.sun.xml.internal.ws.spi.ProviderImpl.createServiceDelegate(Unknown Source) at javax.xml.ws.Service.<init>(Unknown Source) at com.vrv.paw.client.area.VRVRange.<init>(VRVRange.java:48) at com.vrv.paw.client.area.mainTest.main(mainTest.java:12)
然后就是這種百度查資料,查到以下解釋
http://www.nakov.com/blog/2009/07/16/disable-certificate-validation-in-java-ssl-connections/
在開發設計中當我們在java中打開一個SSL連接(比如:java.net.URL.openConnection(“https://….”)),
JSSE實現的SSL協議執行一些驗證以確保這個請求的主機不是假的。
這包括用PKIX算法驗證服務器的X.509證書和檢查主機名稱與證書中的subject是否一致。
如果SSL證書不可信或與目標主機不匹配,HTTPS和SSL加密連接就不能建立並且拋出SSLHandshakeException 或 IOException
By design when we open an SSL connection in Java (e.g. through java.net.URL.openConnection(“https://….”))
the JSSE implementation of the SSL protocol performs few validations to ensure the requested host is not fake.
This involves validation of the server’s X.509 certificate with the PKIX algorithm and checking the host name agains the certificate subject.
If the SSL certificate is not validates as trusted or does not match the target host,
an HTTPS and other SSL encrypted connection cannot be established and all attempts will result in SSLHandshakeException or IOException.
總得來說就是要將SLL數據證書加入到ketstore中
也按照http://www.cnblogs.com/liaojie970/p/4919485.html總提到的方法生成了證書,並且在代碼中
System.setProperty("javax.net.ssl.trustStore", "E:\\vrvcacerts"); System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
package com.vrv.paw.client.area;public class mainTest { public static void main(String[] args) { System.setProperty("javax.net.ssl.trustStore", "E:\\vrvcacerts"); System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); Gson gson = new Gson(); // 同步數據 VRVRange vrvRange = new VRVRange(); VRVRangeSoap vrvRangeSoap = vrvRange.getVRVRangeSoap(); String cString = vrvRangeSoap.login("admin", "123456"); System.out.println(cString); } }
問題依舊存在,最后沒有辦法,就嘗試了在項目中新建wsdl文件,在Eclipse中右鍵該wsdl文件,web service-->Generate Client生成客戶端,具體生成方式見這里
然后再次
package org.tempuri; import java.rmi.RemoteException; import javax.xml.rpc.ServiceException;public class TestClient { public static void main(String[] args) { try { System.setProperty("javax.net.ssl.trustStore", "E:\\jssecacerts"); System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); Gson gson = new Gson(); VRVRange vrvRange = new VRVRangeLocator(); VRVRangeSoap vrvRangeSoap = vrvRange.getVRVRangeSoap(); String login = vrvRangeSoap.login("admin", "123456"); System.out.println(login); } catch (ServiceException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } } }
結果成了。。。。
具體為什么wsimport生成的客戶端代碼不行,我也不知道,如果有哪位大神知道,請指教。