因此,我必须针对在HTTPS网址上托管的WSDL创建服务,并且在创建服务时遇到问题。出于实际原因,我不允许将证书添加到我的信任存储区,因此当我使用自定义SSLSocketFactory执行以下步骤时(因此我们可以动态更改密钥库):
QName name = new QName(qName, QNAME);
Service service = new Client(httpsUrl, name);
port = service.getPort(ClientSoap.class);
我们得到了
的常见错误unable to find valid certification path to requested target
解决此问题的方法是在创建服务之前添加自定义套接字工厂,因此我们的SSL上下文是正确的(详见此处1)
HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory);
然而,这会将应用程序的默认SSLContext污染到我们特定的自定义上下文,并导致应用程序中的其他https调用失败,因为它们使用我们刚刚使用的自定义上下文而不是cacerts上下文。
当我们最初创建服务以使用我们的自定义上下文时,有没有办法呢?
答案 0 :(得分:0)
好吧我通过做一些有点难看的事情(IMO)自己解决了这个问题,但我想我会把它放在这里以防万一其他人遇到这个问题。基本上将原始SSLContext拉入类级变量,然后使用新上下文设置默认值。完成所有处理后,将默认上下文重置为原始上下文。
private SSLSocketFactory originalSocketFactory;
private SSLSocketFactory customSocketFactory;
public void doSomeStuff(){
try {
setSocketFactories();
} catch (CertificateException | IOException | GeneralSecurityException e) {
e.printStackTrace();
}
//do your stuff here
resetOriginalSocketFactory();
}
private void setSocketFactories() throws CertificateException, IOException, GeneralSecurityException {
String jksFile = "C:\\My.jks";
String type = "JKS";
String password="password";
if(null == originalSocketFactory){
originalSocketFactory= HttpsURLConnection.getDefaultSSLSocketFactory();
}
if(null == customSocketFactory){
customSocketFactory = getCustomSocketFactory(jksFile, type, password);
HttpsURLConnection.setDefaultSSLSocketFactory(customSocketFactory);
}
}
private void resetOriginalSocketFactory(){
HttpsURLConnection.setDefaultSSLSocketFactory(originalSocketFactory);
}
private SSLSocketFactory getCustomSocketFactory(String keyStoreLocation, String keystoreType,String password)
throws CertificateException, IOException, GeneralSecurityException {
SSLSocketFactory socketFactory = new SSLSocketFactoryGenerator(keyStoreLocation,keystoreType).getSSLSocketFactory(password);
return socketFactory;
}