簡體   English   中英

向 HttpURLConnection 添加自簽名 SSL 證書

[英]Add a self-signed SSL certificate to HttpURLConnection

我知道關於同一主題還有其他一些問題,但是這些問題都與我的具體問題不符。

在我的 Android 應用程序中,我通過HttpURLConnection向某些 RESTful 端點發出 Http 請求。 其中一些端點使用自簽名證書,其他端點則不使用。 所以我需要一種將自定義 KeyStore 添加到默認 HttpURLConnection 行為的方法。

這是我現在的代碼:

        try {
            KeyStore keyStore = getKeyStore(context);

            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);

            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(keyStore, "pasword".toCharArray());

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

            HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        } catch (KeyStoreException | IOException | CertificateException | NoSuchAlgorithmException | UnrecoverableKeyException | KeyManagementException e) {
            e.printStackTrace();
        }

它有效,但僅適用於自簽名證書,任何其他請求都會產生java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

所以,我正在尋找一種讓 HttpURLConnection 識別自定義自簽名證書而不破壞正常行為的方法。

您基本上有兩種選擇:

  1. 接受任何證書,無論它是否通過忽略證書驗證簽名
  2. 通過將所有證書(甚至是未簽名的)添加到密鑰庫並使用與上述相同的代碼加載它們來信任每個證書,異常應該消失。

我不推薦的選項 1 是創建一個不驗證證書的自定義 TrustManager:

TrustManager[] trustAllCerts = new TrustManager[] { 
    new X509TrustManager() {     
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
            return new X509Certificate[0];
        } 
        public void checkClientTrusted( 
            java.security.cert.X509Certificate[] certs, String authType) {
            } 
        public void checkServerTrusted( 
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    } 
}; 

KeyStore keyStore = getKeyStore(context);

KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, "pasword".toCharArray());

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, null);

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

如果服務器不需要客戶端進行身份驗證,您甚至可以刪除 keymanagerfactory 並使用以下代碼初始化 ssl 上下文:

TrustManager[] trustAllCerts = new TrustManager[] { 
    new X509TrustManager() {     
        public java.security.cert.X509Certificate[] getAcceptedIssuers() { 
            return new X509Certificate[0];
        } 
        public void checkClientTrusted( 
            java.security.cert.X509Certificate[] certs, String authType) {
            } 
        public void checkServerTrusted( 
            java.security.cert.X509Certificate[] certs, String authType) {
        }
    } 
}; 

SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, null);

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM