【问题标题】:Spring WebServiceClient with configurable credentials具有可配置凭据的 Spring WebServiceClient
【发布时间】:2016-07-20 07:34:35
【问题描述】:

我想在 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 spring web-services soap basic-authentication


    【解决方案1】:

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

    【讨论】:

    • 您好@Alexander,这似乎是使用工厂的一个不错的解决方案。没想到。感谢您的提示:D 由于在运行时添加/修改了客户,因此无法使用 AuthScope。我现在就去工厂试一试。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2019-01-07
    • 2020-09-13
    • 2019-11-17
    • 2021-02-12
    • 2015-06-02
    • 2015-07-01
    • 2021-03-12
    • 2016-04-16
    相关资源
    最近更新 更多