Okhttp 访问多个自签名证书 HTTPS 地址解决方案
2020-01-02 本文已影响0人
真胖大海
首先参考
Okhttp 访问自签名证书 HTTPS 地址解决方案
上面这篇博客,解决了访问自签名证书的问题。
但是有时候我们要访问过多域名,每个域名的证书又不一样我们应该怎样做呢
private SSLSocketFactory createSSLSocketFactory() {
SSLSocketFactory ssfFactory = null;
try {
MyTrustManager mMyTrustManager = new MyTrustManager();
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[]{mMyTrustManager}, new SecureRandom());
ssfFactory = sc.getSocketFactory();
} catch (Exception ignored) {
ignored.printStackTrace();
}
return ssfFactory;
}
//实现X509TrustManager接口
public class MyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
//实现HostnameVerifier接口
private class TrustAllHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
/**
* 获去信任自签证书的trustManager
*
* @param ins 自签证书输入流
* @return 信任自签证书的trustManager
* @throws GeneralSecurityException
*/
private X509TrustManager trustManagerForCertificates(InputStream... ins)
throws GeneralSecurityException {
//创建证书工厂
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
//通过证书工厂得到自签证书对象集合
Collection<Certificate> certificates = new ArrayList<>();
for (InputStream inputStream : ins) {
certificates.addAll(certificateFactory.generateCertificates(inputStream));
}
if (certificates.isEmpty()) {
throw new IllegalArgumentException("expected non-empty set of trusted certificates");
}
//为证书设置一个keyStore
char[] password = "password".toCharArray(); // Any password will work.
KeyStore keyStore = newEmptyKeyStore(password);
int index = 0;
//将所有证书放入证书放入keystore中
for (Certificate certificate : certificates) {
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificate);
}
// Use it to build an X509 trust manager.
//使用包含自签证书信息的keyStore去构建一个X509TrustManager
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length == 0) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
return ((X509TrustManager) trustManagers[0]);
}
private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
InputStream in = null; // By convention, 'null' creates an empty key store.
keyStore.load(null, password);
return keyStore;
} catch (IOException e) {
throw new AssertionError(e);
}
}
trustManagerForCertificates.(InputStream...ins)为证书的输入流
比如证书文件有两个 1.crt 和2.crt
X509TrustManager x509TrustManager = trustManagerForCertificates(
new FileInputStream(new File("1.crt")), new FileInputStream(new File("2.crt"))
);
//获取到SSLSocketFactory和X509TrustManager
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(createSSLSocketFactory(),x509TrustManager )
.build();