本文介绍了与基本认证使用HttpComponentsMessageSender WebServiceTemplate的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想测试这是目前使用基本身份验证确保下一个春天的Web服务。对于这些测试,我写了使用Web服务客户端Spring的 WebServiceTemplate 类。

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.

当我创建模板的messageSender,和为 org.springframework.ws.transport.http.CommonsHttpMessageSender 对象豆与 org.apache.commons.httpclient.UsernamePasswordCredentials ,虽然客户端运行时,code的一个警告强调说, CommonsHttpMessageSender 类现在是很precated,我应该使用 HttpComponentsMessageSender 代替。

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.

我曾尝试重新配置客户端的 WebServiceTemplate 使用较新的 HttpComponentsMessageSender 类的工作,但我不能有正确与它配置了基本身份验证的一部分。对于新的 HttpComponentsMessageSender 类,我创建凭证使用 org.apache.http.auth.UsernamePasswordCredentials 类,但是,当我向Web服务调用,凭据似乎是不可用的请求?是否有一个WebServiceTemplate客户随时随地使用这些新类认证请求的工作示例等?

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?

罐核心2.2.0.RELEASE 。

Jars that my working code with old deprecated classes uses: commons-httpclient-3.1, spring-ws-core-2.2.0.RELEASE.

罐:的HttpClient-4.3.4 的HttpCore-4.3.2 弹簧WS-核心2.2.0.RELEASE

测试配置,因为它代表了非工作code:

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;
    }

}

在此先感谢,
PM

Thanks in advance,PM

推荐答案

在最后,使与Spring WebServiceTemplate 基本身份验证工作弹簧WS-xxx.2.2.0.RELEASE 使用电流的HttpClient-4.3 + 的HttpCore-4.3 + 类,我添加了一个preemptive认证拦截到的HttpClient (由@Oliv中建议<一href=\"http://stackoverflow.com/questions/2014700/$p$pemptive-basic-authentication-with-apache-httpclient-4\">$p$pemptive与Apache HttpClient的4 基本身份验证)。需要注意的是,如由@Oliv指出的,这种解决方案增加了认证来发出的所有请求。

In the end, to make Basic Authentication work with the Spring WebServiceTemplate in spring-ws-xxx.2.2.0.RELEASE using current httpclient-4.3.+, httpcore-4.3.+ classes, I've added a preemptive authentication interceptor to the HttpClient (as suggested by @Oliv in Preemptive Basic authentication with Apache HttpClient 4). Note that, as pointed out by @Oliv, this solution adds authentication to ALL requests made.

我现在还不能确定这是否是配置Spring的最好办法 WebServiceTemplate 但它使$ P $的我发现(到目前为止)的唯一途径pemptive验证,而不直接进入的HttpClient HttpClientContext 对象。任何简单更好的答案我会非常欢迎...

I am still not sure if this is the best way to configure the Spring WebServiceTemplate but it is the only way I have found (so far) of enabling preemptive authentication without direct access to the HttpClient's HttpClientContext object. Any simpler better answers I would very much welcome...

拦截code:

private static class PreemptiveAuthInterceptor implements HttpRequestInterceptor {

    public void process(final HttpRequest request, final HttpContext context)
            throws HttpException, IOException {

        AuthState authState = (AuthState) context.getAttribute(
                HttpClientContext.TARGET_AUTH_STATE);

        // If no auth scheme is avaialble yet, initialize it preemptively
        if ( authState.getAuthScheme() == null ) {

            CredentialsProvider credsProvider = (CredentialsProvider) context.getAttribute(
                    HttpClientContext.CREDS_PROVIDER);

            HttpHost targetHost = (HttpHost) context.getAttribute(
                    HttpCoreContext.HTTP_TARGET_HOST);

            Credentials creds = credsProvider.getCredentials(
                    new AuthScope(targetHost.getHostName(), targetHost.getPort()));

            if ( creds == null ) {
                throw new HttpException("no credentials available for preemptive "
                        + "authentication");
            }

            authState.update(new BasicScheme(), creds);
        }
    }
}

这篇关于与基本认证使用HttpComponentsMessageSender WebServiceTemplate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 01:56