信任自签名证书时的Android应用SSL问题

时间:2014-06-29 21:36:31

标签: java android ssl

我的应用程序需要连接到我自己的服务器,因此我将自己的服务器自签名证书添加到KeyStore。它适用于我的服务器,但问题是现在我的应用程序不会接受所有其他证书!例如,如果我尝试连接到https://maps.googleapis.com/,我会收到缺少的证书异常。我怎么能解决这个问题?

以下是我对证书的信任:

public static void setSelfSignedCertSSLContext(AssetManager assets)
        throws Exception {
    // Load self-signed cert from an InputStream
    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    InputStream caInput = assets.open("selfSigned.cer");
    Certificate ca;
    try {
        ca = cf.generateCertificate(caInput);
        Log.d(LOG_TAG, "ca=" + ((X509Certificate) ca).getSubjectDN());
    } finally {
        caInput.close();
    }

    // Create a KeyStore containing our trusted CAs
    String keyStoreType = KeyStore.getDefaultType();
    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
    keyStore.load(null, null);
    keyStore.setCertificateEntry("ca", ca);

    // Create a TrustManager that trusts the CAs in our KeyStore
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    tmf.init(keyStore);

    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory
            .getDefaultAlgorithm());
    kmf.init(keyStore, "changeit".toCharArray());

    // Create an SSLContext that uses our TrustManager
    SSLContext context = SSLContext.getInstance("TLS");
    SSLContext.setDefault(context);

    context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
    HttpsURLConnection.setDefaultSSLSocketFactory(context
            .getSocketFactory());

    HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
        public boolean verify(String string, SSLSession ssls) {
            return true;
        }
    });

    Log.d(LOG_TAG, "SSLContext set successfully");
}

这是我尝试连接到谷歌时遇到的例外情况:

06-29 23:27:59.181: E/AdapterClass(16358): javax.net.ssl.SSLHandshakeException: 
java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

2 个答案:

答案 0 :(得分:1)

您需要创建具有本地(TrustManagerKeyStore和默认TrustManager的自定义TrustManager。当其中一个人找不到证书时,另一个人应该工作。

离。

public class MyTrustManager implements X509TrustManager {

    private X509TrustManager defaultTrustManager;
    private X509TrustManager localTrustManager;

    private X509Certificate[] acceptedIssuers;

    public MyTrustManager(KeyStore localKeyStore) { 
      // init defaultTrustManager using the system defaults
      // init localTrustManager using localKeyStore
    }

    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        try {
            defaultTrustManager.checkServerTrusted(chain, authType);
        } catch (CertificateException ce) {
            localTrustManager.checkServerTrusted(chain, authType);
        }
    }

    //...
}

来源:http://nelenkov.blogspot.com/2011/12/using-custom-certificate-trust-store-on.html

<强> @edit

或者@CommonsWare建议,您可以使用他的CWAC-Security库。它看起来很棒,但我还没有使用它。

答案 1 :(得分:0)

不要尝试以编程方式执行此操作,只需使用keytool将证书添加到现有的cacerts信任存储文件中。