使用HttpClient携带pfx证书调用HTTPS协议的WebService

调用第三方服务时,厂商提供了一个WSDL文件、调用的地址和一个后缀为pfx的证书文件,通过SOUPUI记载证书是可以正常调用WebService服务,那么如何将该服务转换为代码呢?

咨询了厂商的支持,厂商说直接发送报文即可。

观察SOUPUI的调用发现直接发送的SOUP报文,那么决定使用HttpClient进行服务调用,调用HTTPS好说、发送报文也好说,关键问题卡在了pfx证书上面。

百度了很多例子,说JAVA无法直接携带pfx的证书,那么就在pfx证书转换方面尝试了一些,最终没有转换成功。

继续观察SOUPUI的调用模式,SOUPUI可以在PERFERENCE的SSL中可以直接配置keystore和password,就可以携带证书,而且SOUPUI调用各种服务主要是使用HTTPClient完成的的,他可以实现,那就说明通过HTTPClient是可以直接携带pfx格式的证书的,基本思路确定,那就全力在这条路上继续折腾吧。

整理一下尴尬的情况:

资源:HTTPS协议、WebService服务、需要pfx证书认证;

目标:通过HttpClient构建SSL通道调用HTTPS的WebService接口,携带pfx证书信息,直接发送SOUP报文调用接口;

难点:pfx证书如何处理?

百度了好久,有相应的解决方案,但实验后均不行;后在bing的国际版中进行搜索,结果中stackoverflow中有了大收获。

地址:https://stackoverflow.com/questions/44493040/apache-httpclient-pfx-file

该国际友人碰到了和我一样的问题,通过SOUPUI携带pfx证书调用Https的WebService服务没有问题,使用HttpClient模拟报文的时候无法携带证书,但是该哥们自行解决了该问题,而且还无私的把源代码整个贴在了论坛上,我用颤抖的双手复制粘贴了该代码,稍作修改执行发现问题解决。天哪,折腾了一个下午加晚上,终于算是解决了。

在此特意转发一下这位大神的佳作:

KeyStore clientStore  = KeyStore.getInstance("PKCS12"); 
InputStream instream = Thread.currentThread().getContextClassLoader().getResourceAsStream(keystoreName);
try {
    clientStore.load(instream, keyStorePwd.toCharArray());
} finally {
    instream.close();
}
//Trust everybody
X509TrustManager tm = new X509TrustManager() {
    @Override
    public void checkClientTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException {}
    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws CertificateException {}
    @Override
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {return null;}
};
SSLContext sslCtx = SSLContext.getInstance("TLS");
KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmfactory.init(clientStore, keyStorePwd != null ? keyStorePwd.toCharArray() : null);
KeyManager[] keymanagers = kmfactory.getKeyManagers();
sslCtx.init(keymanagers, new TrustManager[]{tm}, null);
SSLConnectionSocketFactory sslConnectionFactory = new SSLConnectionSocketFactory(sslCtx);
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("https", sslConnectionFactory).register("http", new PlainConnectionSocketFactory()).build();
PoolingHttpClientConnectionManager pcm = new PoolingHttpClientConnectionManager(registry);
HttpClientBuilder hcb = HttpClientBuilder.create();
hcb.setConnectionManager(pcm);
CloseableHttpClient httpClient = hcb.build();
原文地址:https://www.cnblogs.com/xusweeter/p/7659762.html