我知道同一主题上还有其他问题,但是这些问题都不等于我的特定问题。
在我的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,创建一个不验证证书的自定义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());