我使用自定义SSL工厂自定义JAX-WS:
Map<String, Object> requestContext = ((BindingProvider) port).getRequestContext();
SSLSocketFactory sslSocketFactory = sslSocketFactoryGenerator.getSSLSocketFactory();
requestContext.put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory",sslSocketFactory);
requestContext.put("com.sun.xml.ws.transport.https.client.SSLSocketFactory", sslSocketFactory);
getSSLSocketFactory()
方法执行以下操作:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(keyManagers, trustManagers, new SecureRandom());
return sslContext.getSocketFactory();
trustManagers
的构建方式如下:
TrustManagerFactory tmFact = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
tmFact.init(getTrustStore());
return tmFact.getTrustManagers();
getTrustStore()
方法:
KeyStore getKeyStore() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
{
try(FileInputStream fis = new FileInputStream(trustStorePath))
{
KeyStore ks = KeyStore.getInstance("jks");
ks.load(fis, getTrustStorePass().toCharArray());
return ks;
}
}
当我现在执行SOAP请求时,可以看到以下SSL调试日志:
trustStore is: /etc/pki/java/cacerts
trustStore type is : jks
trustStore provider is :
init truststore
trustStore路径与我提供的路径不同,大概是默认路径。该受托人不包含我需要的证书,因此我的SSL连接失败。
当我通过设置SSL系统属性运行应用程序时:
-Djavax.net.ssl.trustStore=/my/path/to/trustore
-Djavax.net.ssl.trustStorePassword=myPass
然后它可以正常工作。
我做错了什么?我是否需要以其他方式设置JAX-WS?
我将应用程序托管在Amazon AMI linux上的Tomcat 9,openjdk-1.8中。
更新
为此找到了解决方案。我们实际上使用JAX-WS的Apache CXF实现。它几乎忽略了com.sun.xml.ws.transport.https.client.SSLSocketFactory
的JAX-WS设置。我通过创建自定义属性来修复它,并将其传递给上下文:
TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setUseHttpsURLConnectionDefaultSslSocketFactory(false);
tlsParams.setSSLSocketFactory(sslSocketFactory);
requestContext.put(TLSClientParameters.class.getName(), tlsParams);
这里正在讨论相同的问题: