向HttpURLConnection添加自签名SSL证书

问题描述 投票:0回答:1

我知道同一主题上还有其他问题,但是这些问题都不等于我的特定问题。

在我的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识别自定义的自签名证书而又不破坏正常的行为。

android ssl httpurlconnection self-signed
1个回答
0
投票

您基本上有两个选择:

  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());

如果服务器不需要客户端进行身份验证,您甚至可以使用以下代码来删除密钥管理工厂并初始化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());
© www.soinside.com 2019 - 2024. All rights reserved.