在linux下tomcat報javax.net.ssl.SSLHandshakeException sun.security.validator.ValidatorException: PKIX

在本地windows環境Java服務器 訪問https服務器沒有問題,換到測試環境linux服務器訪問時出現上面這個問題,

是證書出問題了,服務器不信任我們自己創建的證書,所以在代碼中必須要忽略證書信任問題。只要在創建connection之前調用兩個方法: 

        trustAllHttpsCertificates();  

       HttpsURLConnection.setDefaultHostnameVerifier(hv);

兩個方法的具體實現,如下:

  1. HostnameVerifier hv = new HostnameVerifier() {  
  2.         public boolean verify(String urlHostName, SSLSession session) {  
  3.             System.out.println("Warning: URL Host: " + urlHostName + " vs. "  
  4.                                + session.getPeerHost());  
  5.             return true;  
  6.         }  
  7.     };  
  8.       
  9.     private static void trustAllHttpsCertificates() throws Exception {  
  10.         //創建信任管理器來信任所有的證書
  11.         javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];  
  12.         javax.net.ssl.TrustManager tm = new miTM();  
  13.         trustAllCerts[0] = tm;  
  14.         //實例化SSL協議
  15.         javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext  
  16.                 .getInstance("SSL");  
  17.         //實例化SSl協議 信任所有證書
  18.         sc.init(null, trustAllCerts, null);  
  19.         javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc  
  20.                 .getSocketFactory());  
  21.     }  
  22.   
  23.     static class miTM implements javax.net.ssl.TrustManager,  
  24.             javax.net.ssl.X509TrustManager {  
  25.         public java.security.cert.X509Certificate[] getAcceptedIssuers() {  
  26.             return null;  
  27.         }  
  28.   
  29.         public boolean isServerTrusted(  
  30.                 java.security.cert.X509Certificate[] certs) {  
  31.             return true;  
  32.         }  
  33.   
  34.         public boolean isClientTrusted(  
  35.                 java.security.cert.X509Certificate[] certs) {  
  36.             return true;  
  37.         }  
  38.   
  39.         public void checkServerTrusted(  
  40.                 java.security.cert.X509Certificate[] certs, String authType)  
  41.                 throws java.security.cert.CertificateException {  
  42.             return;  
  43.         }  
  44.   
  45.         public void checkClientTrusted(  
  46.                 java.security.cert.X509Certificate[] certs, String authType)  
  47.                 throws java.security.cert.CertificateException {  
  48.             return;  
  49.         }  
  50.     } 

以上的解決辦法來自http://mengyang.iteye.com/blog/575671,在這裏記錄一下這個問題。

這裏簡單介紹下HostnameVerifier,這個接口主要是javax.net.ssl用於主機名驗證的基接口。

其中verify()這個方法驗證主機名和服務器驗證方案,這裏重寫了這個方法在連接期間,如果URL的主機名和服務器名不匹配則驗證機制可以回調此藉口的實現程序來確定是否應該允許此鏈接。

TrustManager從Java API那看是

就是信任管理器負責管理在進行信任決策時使用的信任材料,以及決定是否應該接受對等方提供的憑據。通過使用TrustManagerFactory或通過實現TrustManager子類之一來創建信任管理器。

SSLContext類:

這個類的實例 代表socket協議實現,它作爲socket工廠或SSLEngress的工廠。這個類用一組可選的密鑰和信任管理器和安全隨機字節的源進行初始化。Java平臺的每一個實現都需要支持以下標準SSLVIEW協議。

HostnameVerifier接口:

在握手期間,如果URL的主機名和服務器的標識主機名不匹配,驗證機制可以調用該接口的實現者來確定是否應該允許該連接。

這個策略可以是基於證書的,或者可以依賴於其他認證方案。當URL主機名驗證的默認規則失敗時,將使用這個回調。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章