Axis 1.x 編寫的client在測試https的webservice的時候, 由于client 代碼建立SSL連接的時候沒有對truststore進行設置,在與https部署的webservice 連接會在運行時報出:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
這是由于Axis的client用默認的SocketFactory,會對server端的證書進行驗證,我們的測試server是自簽名的,client檢測到后自動斷開連接,握手失敗。
網上很多解決方案是用sun的keytool生成clientTrustStore和serverTrustStrore并把證書導進去,這些方法都稍顯繁瑣,我們這種client測試類沒必要做一些程序之外的工作,所以綜合了一個解決方案,想到這個辦法。此方法的靈感來自于axis文檔里的dirty solution。
核心思想是自己做一個不對證書做任何檢查的SocketFactory,并用這個socket factory來替換Axis本身用的SocketFactory, 為了方便,MySocketFactory直接繼承Axis的父類JSSESocketFactory 。并且重寫父類方法
protected void initFactory() throws IOException
initFactory方法的內容,很簡單,就是讓checkServerTrusted/checkClientTrusted什么都不返回,然后最后一行將這個SslSocketFactory賦給我們自定義類里的sslFactory變量。
// Create a trust manager that does not validate certificate chains TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { // Trust always } public void checkServerTrusted(X509Certificate[] certs, String authType) { // Trust always } } }; // Install the all-trusting trust manager SSLContext sc = SSLContext.getInstance("SSL"); // Create empty HostnameVerifier HostnameVerifier hv = new HostnameVerifier() { public boolean verify(String arg0, SSLSession arg1) { return true; } }; sc.init(null, trustAllCerts, new java.security.SecureRandom());
sslFactory = sc.getSocketFactory;
Axis client測試類中用
AxisProperties.setProperty("axis.socketSecureFactory","my.test.MySocketFactory")來指定Axis類庫要調用的SocketFactory,就是之前被我們改寫的不對server certificate做任何驗證的Factory。
這個解決方式絕對簡單,不需要跟其他方式一樣用sun的keytool建立導入一些本地證書,并利用了Axis自己的機制處理證書驗證問題。
文章列表