2012-01-01 167 views
4
URL myUrl = new URL("https://www....."); 

網站的SSL證書已過期。如何避免它,並使URL()工作?java - 忽略過期的ssl證書

+0

URL投擲CertificateExpiredException? @Dikobraz – 2015-04-29 09:32:05

回答

15

你應該建立一個TrustManager換行默認的信任管理器,捕捉CertificiateExpiredException並忽略它。

注意:如this answer所述,這是否安全取決於實施。特別是,它依賴於最後完成的日期驗證,在正確檢查了其他所有內容之後。

東西沿着這些路線應該工作:

TrustManagerFactory tmf = TrustManagerFactory.getInstance(
    TrustManagerFactory.getDefaultAlgorithm()); 
// Initialise the TMF as you normally would, for example: 
tmf.init((KeyStore)null); 

TrustManager[] trustManagers = tmf.getTrustManagers(); 
final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0]; 

TrustManager[] wrappedTrustManagers = new TrustManager[]{ 
    new X509TrustManager() { 
     public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
      return origTrustmanager.getAcceptedIssuers(); 
     } 

     public void checkClientTrusted(X509Certificate[] certs, String authType) { 
      origTrustmanager.checkClientTrusted(certs, authType); 
     } 

     public void checkServerTrusted(X509Certificate[] certs, String authType) { 
      try { 
       origTrustmanager.checkServerTrusted(certs, authType); 
      } catch (CertificateExpiredException e) {} 
     } 
    } 
}; 

SSLContext sc = SSLContext.getInstance("TLS"); 
sc.init(null, wrappedTrustManagers, null); 
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 

信託經理拋出CertificateException S(詳見子類),什麼是錯用證書。具體說明你想要捕捉/忽略的內容。在你捕獲的東西可能被拋出之前,你真正要驗證的所有東西都必須被檢查,否則你也必須手動驗證它。比這更輕鬆的任何事情(尤其是沒有做任何事情,因此不會拋出任何異常)將完全忽略證書驗證和驗證,這與使用匿名密碼套件或忽略驗證大致相同。這將破壞使用SSL/TLS的安全性目的(而不是僅在有效期限內更靈活)。

+0

此代碼完全不起作用。執行tmf.getTrustManagers()時,您將得到「TrustManagerFactory未初始化」的異常。請在未來發布之前測試您的代碼。我花了一個多小時試圖找出如何解決這個問題。 – AndroidDev 2012-12-06 08:00:59

+1

@AndroidDev,對不起,我假設OP會知道TMF應該像平常一樣初始化,但是你可能是對的,這並不明顯。 (剛剛編輯。) – Bruno 2012-12-06 10:39:50

+0

總是javax.net.ssl.SSLHandshakeException:連接已關閉peer – 2016-06-14 14:09:37

2

您必須創建一個將忽略過期證書的自定義X509驗證程序。事實上,不會執行檢查。從這裏取

代碼:http://exampledepot.com/egs/javax.net.ssl/TrustAll.html

// Create a trust manager that does not validate certificate chains 
TrustManager[] trustAllCerts = new TrustManager[]{ 
    new X509TrustManager() { 
     public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
      return null; 
     } 
     public void checkClientTrusted(
      java.security.cert.X509Certificate[] certs, String authType) { 
     } 
     public void checkServerTrusted(
      java.security.cert.X509Certificate[] certs, String authType) { 
     } 
    } 
}; 

// Install the all-trusting trust manager 
try { 
    SSLContext sc = SSLContext.getInstance("SSL"); 
    sc.init(null, trustAllCerts, new java.security.SecureRandom()); 
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); 
} catch (Exception e) { 
} 

// Now you can access an https URL without having the certificate in the truststore 
// It should work with expired certificate as well 
try { 
    URL myUrl = new URL("https://www....."); 
} catch (MalformedURLException e) { 
} 
+2

請避免複製/粘貼/傳播完全禁用安全檢查的代碼,正如'TrustManager'所做的:這首先破壞了使用SSL/TLS的要點。 – Bruno 2012-01-01 17:21:38

+0

當某些移動設備中的電池被移除時,日期將重置爲1980年的舊日期,這會導致您的SSL證書由於失效日期而失敗。這可能會導致您的應用程序失敗,如果您的應用程序即使使用過期證書仍然可以繼續工作至關重要,忽略失效日期非常重要。 – AndroidDev 2012-12-06 06:22:01

+0

@AndroidDev如果您的批評意在解決布魯諾的評論,那麼請注意,接受任何證書和過期的可信證書之間存在巨大差異。此外,由於許多原因,嚴重用戶調整日期。 – 2013-01-10 02:35:09

1

我寫了一個自定義的TrustManager來解決這個問題,你可以在https://gist.github.com/divergentdave/9a68d820e3610513bd4fcdc4ae5f91a1看到它。此TrustManager將有問題的X509Certificate包裝在另一個類中,以禁用到期檢查,同時保留所有其他驗證。 (即匹配主機名,鏈接到受信任的CA,簽名有效等)

+0

不錯的例子,我試過了,只是爲了查看沒有任何** checkValidity **方法被調用。唯一被觸發的回調是** getEncoded **和** getPublicKey **。不知道是否與我使用本地密鑰庫,加載了固定證書的事實有關? – jayeffkay 2017-10-07 13:21:54

+0

@jayeffkay我在本地嘗試了這一點,我看到了幾種被調用的方法。我看到'checkValidity'被調用,但我不得不設置方法斷點而不是行號斷點,因爲這些方法具有空體。 我不確定固定證書是否會有所作爲,但是如果您使用自簽名證書作爲可能會改變行爲的服務器證書(而不是證書)。如果TLS服務器的公共與您的信任存儲中的自簽名證書的公鑰相同,那麼其餘的檢查都是沒有意義的。 (沒有測試過會發生什麼) – dncook 2017-10-08 17:51:57