快速方法:
KeyStore cacertsKeyStore = KeyStoreUtil.getCacertsKeyStore();
一、需求背景
??????在使用HttpClient来设置server端提供的第三方证书的时候, 自己创建了一个空的KeyStore对象,然后再往空的KeyStore对象中放入第三方证书。但是这样会导致一个结果就是不能使用jdk提供的大证书,也就不能访问像百度这样的官方网站的https服务。
二、经历过程
1、使用HttpClient 4.5默认的创建连接池的方法为:
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
2、如果使用这个对象来创建连接池则你能正常的访问像百度这样的官方https服务,证明这个构造方法里面肯定加载了相关的证书,所以继续进入到方法里面去,发现https其实是加载了一个SSLConnectionSocketFactory对象:
private static Registry<ConnectionSocketFactory> getDefaultRegistry() {
return RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
}
3、再往源码走几步进入到获取KeyStore对象的代码中去,这里创建出来的对象就是一个存放了jdk证书的KeyStore对象: 4、查看这个getCacacertsKeyStore(“trustmanager”)方法,发现这个方法其实就是去加载了jre里面的一个cacerts文件: 对应的证书文件如下:
5、到这里问题就已经解决了,可以看到HttpClient就是加载了JDK中的cacerts证书文件,这个证书文件中大概有100多个证书。 6、如果想自己想要添加一个第三方证书又想能访问这些jdk已经带的证书,则可以通过如下代码来定义自己的keyStore:
public static KeyStore createKeyStore(ArrayList<InputStream> certificatePathList) throws CertificateException {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
KeyStore keyStore = null;
try {
keyStore = KeyStoreUtil.getCacertsKeyStore();
int index = 0;
for (InputStream inputStream : certificatePathList) {
Certificate certificate = certificateFactory.generateCertificate(inputStream);
String certificateAlias = Integer.toString(index++);
keyStore.setCertificateEntry(certificateAlias, certificate);
}
} catch (Exception e) {
e.printStackTrace();
}
return keyStore;
}
|