问题描述
我想测试这是目前使用基本身份验证确保下一个春天的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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!