我需要使用 SSL 证书通过 HTTPS 调用外部 Web 服务端点。正确的方法应该是使用 BindingProvider 设置自定义 SSLSocketFactory,但我无法让它工作。为了让连接正常工作,我必须设置一个默认的 SSLSocketFactory:
public void secureStoreSignedOffPdf(String filename, byte[] signedOffPdf, URL endpoint, String applicationEnvironmentId) {
final SSLSocketFactory defaultSslSocketFactory = HttpsURLConnection.getDefaultSSLSocketFactory();
final SSLSocketFactory wsSslSocketFactory = SslHelper.buildWebServiceSslSocketFactory(applicationEnvironmentId);
// TODO Fix: this should work only setting the property with BindingProvider (see below)
HttpsURLConnection.setDefaultSSLSocketFactory(wsSslSocketFactory);
final StoragePortService storagePortService = new StoragePortService();
final StoragePort storagePort = storagePortService.getStoragePortSoap11();
final BindingProvider bindingProvider = (BindingProvider) storagePort;
bindingProvider.getRequestContext()
.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpoint.toString());
bindingProvider.getRequestContext()
.put("com.sun.xml.ws.transport.https.client.SSLSocketFactory", wsSslSocketFactory);
final StorageRequest storageRequest = new StorageRequest();
final Document document = new Document();
document.setContent(new DataHandler(new ByteArrayDataSource(signedOffPdf, PDF_CONTENT_TYPE)));
document.setName(filename);
storageRequest.setOverwrite(true);
storageRequest.setBaseDocument(document);
final StorageResponse storageResponse = storagePort.storage(storageRequest);
HttpsURLConnection.setDefaultSSLSocketFactory(defaultSslSocketFactory);
if (!storageResponse.getReturnCode()
.equalsIgnoreCase(RESPONSE_OK)) {
throw new IllegalStateException("Web service failed with error: "
+ storageResponse.getReturnCode()
+ " - "
+ storageResponse.getReturnMessage());
}
}
如果我删除这一行:
bindingProvider.getRequestContext().put("com.sun.xml.ws.transport.https.client.SSLSocketFactory", wsSslSocketFactory);
该代码仍然有效(因为我使用的是 HttpsURLConnection.setDefaultSSLSocketFactory 方法)。但是如果在那一行我放了一个错误的 SSLSocketFactory,它就会失败,所以这意味着放工厂属性会做一些事情。
我没有得到的是没有设置默认 SSLSocketFactory 的调用:
HttpsURLConnection.setDefaultSSLSocketFactory(...)
仅供参考:我已经尝试过:
bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", wsSslSocketFactory);
但它什么也没做。