我的应用程序需要连接到我自己的服务器,因此我将自己的服务器自签名证书添加到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.
答案 0 :(得分:1)
您需要创建具有本地(TrustManager
)KeyStore
和默认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信任存储文件中。