java - 具有可配置凭据的 Spring WebServiceClient

标签 java spring web-services soap basic-authentication

我想在 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);
}

非常感谢您的帮助, 新

最佳答案

最通用的解决方案是创建一个常规 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/credentials 对)来创建常规的 Spring bean。 Apache HttpClient 将根据目的地自动选择正确的用户名/密码对。

关于java - 具有可配置凭据的 Spring WebServiceClient,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38475065/

相关文章:

java - 如何在NamedQuery中编写NamedQuery haversine公式?

java - 将文件(图像)从 Android 设备发送到使用 REST 编写的服务器上的 Web 服务

java - 发送文件到android服务器

java - 打开其他布局时,应用已停止

java - 找不到符号 findViewById

java - ResourceBundleMessageSource 解决错误

java - 用于 REST 服务的 Jersey 和 Spring 的 @Autowired 属性上的 NullPointerException

java - spring jdbc 模板返回空结果

java - 是否可以在 spring boot 中创建一个通用的 CRUD

web-services - 为第 3 方 WS 生成 stub 类