I am trying to test a Spring Web Service which is currently secured with Basic Authentication underneath. For these tests, I have written a Web Service client using Spring's WebServiceTemplate class.
My Web Service client calls to the Web Service work okay when I create the template's MessageSender as a org.springframework.ws.transport.http.CommonsHttpMessageSender object bean with org.apache.commons.httpclient.UsernamePasswordCredentials and, although the client works, the code has a warning highlighted saying that the CommonsHttpMessageSender class is now deprecated and that I should be using HttpComponentsMessageSender instead.
I have tried re-configuring the client's WebServiceTemplate to work using the newer HttpComponentsMessageSender class, but I am unable to have the basic auth part configured correctly with it. For the new HttpComponentsMessageSender class, I have created credentials using the org.apache.http.auth.UsernamePasswordCredentials class but, when I make a call to the Web Service, the credentials seem to not be available with the request? Is there a working example of a WebServiceTemplate client anywhere that uses these newer classes for authenticating requests, etc?
Jars that my working code with old deprecated classes uses: commons-httpclient-3.1,  spring-ws-core-2.2.0.RELEASE.
Jars that my NON-working code with newer classes uses: httpclient-4.3.4, httpcore-4.3.2, spring-ws-core-2.2.0.RELEASE.
Test Configuration as it stands for NON-working code:
package com.company.service.a.ws.test.config;
import java.io.IOException;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
import org.springframework.ws.transport.http.HttpComponentsMessageSender;
@PropertySource("classpath:/${environment}-use-case-data.properties")
@ComponentScan(basePackages = "com.company.service.a.ws.test")
@Configuration
public class TestConfig {
    @Value("${ws.url}")
    private String wsUrl;
    @Value("${ws.username}")
    private String username;
    @Value("${ws.password}")
    private String password;
    private static final Logger logger = LogManager.getLogger();
    @Bean
    public SaajSoapMessageFactory messageFactory() {
        return new SaajSoapMessageFactory();
    }
    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("com.company.service.a.ws.model.data");
        return marshaller;
    }
    @Bean RequestConfig requestConfig() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setAuthenticationEnabled(true)
                .build();
        return requestConfig;
    }
    @Bean
    @DependsOn( value = "propertyConfigurer" )
    public UsernamePasswordCredentials credentials() {
        logger.debug("creating credentials for username: {} passowrd={}", 
                username, password);
        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(
                username, password);
        return credentials;
    }
    @Bean 
    public CredentialsProvider credentialsProvider() {
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, credentials());
        return credentialsProvider;
    }
    private static class ContentLengthHeaderRemover implements HttpRequestInterceptor{
        @Override
        public void process(HttpRequest request, HttpContext context) 
                throws HttpException, IOException {
            // fighting org.apache.http.protocol.RequestContent's 
            // ProtocolException("Content-Length header already present");
            request.removeHeaders(HTTP.CONTENT_LEN);
        }
    }
    @Bean
    public HttpComponentsMessageSender messageSender() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setAuthenticationEnabled(true)
                .build();
        HttpClientBuilder httpClientBuilder = HttpClients.custom();
        HttpClient httpClient = httpClientBuilder
                .addInterceptorFirst(new ContentLengthHeaderRemover())
                .setDefaultRequestConfig(requestConfig)
                .setDefaultCredentialsProvider(credentialsProvider())               
                .build();
        HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender(httpClient);
        return messageSender;
    }
    @Bean( name = "propertyConfigurer" )
    public static PropertySourcesPlaceholderConfigurer propertyConfigurer() {
        PropertySourcesPlaceholderConfigurer configurer = 
                new PropertySourcesPlaceholderConfigurer();
        return configurer;
    }
    @Bean
    public WebServiceTemplate webServiceTemplate() {
        logger.debug("creating webServiceTemplate to url: {}", wsUrl);
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate(messageFactory());
        webServiceTemplate.setDefaultUri(wsUrl);
        webServiceTemplate.setMarshaller(marshaller());
        webServiceTemplate.setUnmarshaller(marshaller());
        webServiceTemplate.setMessageSender(messageSender());
        return webServiceTemplate;
    }
}
Thanks in advance, PM
This is workout for our project using org.apache.httpcomponents :
httpclient-4.5.3, httpcore-4.4.6  
We create interceptor header RequestDefaultHeaders reqHeader = new RequestDefaultHeaders(headers) and then add to httpClient using .addInterceptorLast(reqHeader) when building CloseableHttpClient
Configuration class :
import org.apache.http.message.BasicHeader;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.Header;
import org.apache.http.client.protocol.RequestDefaultHeaders;
@Bean
HttpClient createHttpClient() {
    List<Header> headers = new ArrayList<>();
    BasicHeader authHeader = new BasicHeader("Authorization", "Basic " + base64authUserPassword());
    headers.add(authHeader);
    // add more header as more as needed
    RequestDefaultHeaders reqHeader = new RequestDefaultHeaders(headers);
    CloseableHttpClient httpClient = 
        HttpClients.custom()
            .addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor())
            .addInterceptorLast(reqHeader)
            .build();
    return httpClient;
}
@Bean
public HttpComponentsMessageSender defaultMyMessageSender() 
        throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
    HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender(createHttpClient());
    //messageSender.setCredentials(credentials());
    return messageSender;
}
@Bean
WebServiceTemplate webServiceTemplate() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException{
    WebServiceTemplate wsTemplate = new WebServiceTemplate();
    wsTemplate.setDefaultUri(endpointURI);
    wsTemplate.setMessageSender(defaultMyMessageSender());
    return wsTemplate;
}
                        One solution I have used is to create a custom WebServiceMessageSender with a custom CredentialsProvider. This solution also sets a route planner that respects the default java proxy settings.
@Configuration
public class WebServiceConfiguration {
    @Bean
    public WebServiceMessageSender webServiceMessageSender(@Value("${endpoint.uri}") endpointUri, 
                                                           @Value("${endpoint.username}") String username, 
                                                           @Value("${endpoint.password}") String password) throws Exception {
        SystemDefaultRoutePlanner routePlanner = new SystemDefaultRoutePlanner(
            ProxySelector.getDefault());
        BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(new AuthScope(endpointUri.getHost(), endpointUri.getPort(), ANY_REALM, ANY_SCHEME), new UsernamePasswordCredentials(username, password););
        CloseableHttpClient httpclient = HttpClients.custom()
            .setRoutePlanner(routePlanner)
            .addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor())
            .setDefaultCredentialsProvider(credentialsProvider)
            .build();
        return new HttpComponentsMessageSender(httpclient);
    }
}
                        Use HttpComponentsMessageSender with UsernamePasswordCredentials. Note that HttpComponentsMessageSender must be created as Spring bean or you must call afterPropertiesSet manually to be http client correctlly set up.
This works for me:
@Configuration
public class WsClientConfiguration {
    @Bean
    public ESignatureProcessorClient eSignatureProcessorClient() {
        ESignatureProcessorClient client = new ESignatureProcessorClient();
        client.setWebServiceTemplate(mwWebServiceTemplate());
        return client;
    }
    @Bean
    public WebServiceTemplate mwWebServiceTemplate() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("cz.csas.services.esignatureprocessor.v02_02");
        WebServiceTemplate template = new WebServiceTemplate(marshaller, marshaller);
        template.setDefaultUri("https://osb-st2.vs.csin.cz:5001/CSMW/WS_MW_ESignatureProcessor_v02_02");
        template.setMessageSender(defaultMwMessageSender());
        return template;
    }
    @Bean
    public HttpComponentsMessageSender defaultMwMessageSender() {
        HttpComponentsMessageSender messageSender = new HttpComponentsMessageSender();
        messageSender.setCredentials(new UsernamePasswordCredentials("user", "password"));
        return messageSender;
    }
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With