我想在Spring中使用可配置的凭据创建SOAP Web服务客户端。 将使用相同的实现来使用不同的用户/通过身份验证来呼叫不同的客户。 将使用基本身份验证。
与spring ws WebServiceTemplate credentials类似,但每次通话都有不同的凭据。
有没有更好的方法来获取WebServiceMessageSender并且每次都设置凭据? 如果我这样做,与其他客户并行完成的请求会发生什么?
当前配置
@Bean
public WebServiceTemplate webServiceTemplate(){
WebServiceTemplate template = new WebServiceTemplate();
template.setMessageSender(messageSender());
return template;
}
@Bean
public HttpComponentsMessageSender messageSender(){
HttpComponentsMessageSender sender = new HttpComponentsMessageSender();
return sender;
}
网络服务客户端
public Status updateStatus(URL url, String user, String password,PackageStatus request){
WebServiceTemplate template = getWebServiceTemplate();
//TODO set credentials here ???
return (Status) template.marshalSendAndReceive(request);
}
非常感谢你的帮助, 新
答案 0 :(得分:3)
最常见的解决方案是创建一个常规Java工厂类,该工厂类将根据凭据创建Web服务模板。下面是一个使用apache HttpComponents版本4.3的示例:
class WebServiceTemplateFactory {
//@Autowired - all dependencies that don't change, such as WebServiceMessageFactory, Marshaller etc.
WebServiceTemplate createWebServiceTemplate(String user, String pwd) throws Exception {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
//create the HTTP client
RequestConfig requestConfig = RequestConfig.custom().setStaleConnectionCheckEnabled(true).build(); //can set more stuff like connection timeout etc.
SSLContext sslContext = SSLContexts.custom().build();
SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext, null, null, SSLConnectionSocketFactory.STRICT_HOSTNAME_VERIFIER);
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, pwd));
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setSSLSocketFactory(sslSocketFactory)
.setDefaultCredentialsProvider(credentialsProvider)
.addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor()) //preventing 'org.apache.http.ProtocolException: Content-Length header already present' exception
.build();
//create the message sender
HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender(httpClient);
messageSender.afterPropertiesSet(); // just for consistency - not expecting much from this call
webServiceTemplate.setMessageSender(messageSender);
//... set the rest of dependencies, if needed
return webServiceTemplate;
}
}
这是我看到的最基本的解决方案。 您可以通过不为同一用户名创建单独的客户端来优化它。您也可以为所有这些客户端提供单个客户端 - 检查Apache HttpComponents文档(或您使用的其他底层客户端的文档)。
请注意,Spring-WS本身并不实现客户端,它只是一些现有HTTP客户端的包装器。
更新:
如果您使用的是Apache HttpClient,请检查它们对AuthScope的使用情况。您可以为所有目标(主机,端口)创建单个HttpClient,每个目标都有自己的用户名/密码对。但你必须提前知道它们。如果是这种情况,那么上面的代码(修改为设置所有AuthScope /凭证对)可用于创建常规Spring bean。 Apache HttpClient将根据目的地自动选择正确的用户名/密码对。