Java 向WS-Outbound网关添加动态HTTP头
我想使用一些定制的HTTP头来丰富我的HTTP/SOAP请求(使用WS-Outbound Gateway发送),具体取决于Java 向WS-Outbound网关添加动态HTTP头,java,web-services,spring-integration,spring-ws,Java,Web Services,Spring Integration,Spring Ws,我想使用一些定制的HTTP头来丰富我的HTTP/SOAP请求(使用WS-Outbound Gateway发送),具体取决于消息实际包含的内容,即 为每个请求添加基本身份验证,其中凭据取决于某些消息头 仅当存在特定的消息头时添加自定义HTTP头 我考虑了以下解决办法: 实现自定义ClientInterceptor——但无法访问 此时的Message.header 实现定制的SoapHeaderMapper——可以访问Message.header,但我不喜欢这个想法,因为它的意思是 在SOAP信
消息
实际包含的内容,即
- 为每个请求添加基本身份验证,其中凭据取决于某些
消息头
- 仅当存在特定的
消息头时添加自定义HTTP头
ClientInterceptor
——但无法访问
此时的Message.headerSoapHeaderMapper
——可以访问Message.header
,但我不喜欢这个想法,因为它的意思是
在SOAP信封上操作,而不是在连接/请求级别李>
WebServiceMessageCallback
——此时无法访问消息HttpClient
至此,我完成了定制的HttpComponentsMessageSender
,它为每个请求设置HttpClientContext
。问题是,仍然无法访问Mesage.headers
,因此我完成了ServiceActivator
与SPEL和ThreadLocal
的组合,如下所示
一般来说它是有效的,但是。。。还有其他更正确的途径吗
<int:service-activator expression="@basicAuthenticationMessageSender.setBasicAuth(#root, headers.username, headers.pass)" />
public class BasicAuthenticationMessageSender extends HttpComponentsMessageSender {
private static ThreadLocal<HttpClientContext> httpClientContextLocal = new ThreadLocal<>();
@Override
protected HttpContext createContext(URI uri) {
HttpClientContext httpClientContext = httpClientContextLocal.get();
// This part makes authentication preemptive:
HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
AuthCache authCache = new BasicAuthCache();
authCache.put(targetHost, new BasicScheme());
httpClientContext.setAuthCache(authCache);
return httpClientContext;
}
public GenericMessage setBasicAuth(GenericMessage message, String username, String password) throws Exception {
final HttpClientContext httpClientContext = HttpClientContext.create();
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
httpClientContext.setCredentialsProvider(credentialsProvider);
httpClientContextLocal.set(httpClientContext);
return message;
}
}
公共类BasicAuthenticationMessageSender扩展了HttpComponents消息Sender{
私有静态ThreadLocal httpClientContextLocal=新ThreadLocal();
@凌驾
受保护的HttpContext createContext(URI){
HttpClientContext HttpClientContext=httpClientContextLocal.get();
//这一部分使身份验证优先:
HttpHost targetHost=新的HttpHost(uri.getHost(),uri.getPort(),uri.getScheme());
AuthCache AuthCache=new BasicAuthCache();
put(targetHost,newbasicscheme());
httpClientContext.setAuthCache(authCache);
返回httpClientContext;
}
公共GenericMessage setBasicAuth(GenericMessage消息、字符串用户名、字符串密码)引发异常{
最终的HttpClientContext HttpClientContext=HttpClientContext.create();
CredentialsProvider CredentialsProvider=新的BasicCredentialsProvider();
setCredentials(AuthScope.ANY,新用户名密码Credentials(用户名,密码));
httpClientContext.setCredentialsProvider(credentialsProvider);
httpClientContextLocal.set(httpClientContext);
返回消息;
}
}
Spring集成4.3.11没错。因为SpringIntegrationWS支持完全基于SpringWS项目,所以我们在SI中不能再看到SWS为我们提供的东西了 无论如何,您可以将
WebServiceMessageCallback
注入AbstractWebServiceOutboundGateway
中,在调用此WS-Gateway之前,可以访问填充在此处的消息的ThreadLocal
变量
在WebServiceMessageCallback
中,您应该可以访问:
TransportContext context = TransportContextHolder.getTransportContext();
HttpUrlConnection connection = (HttpUrlConnection) context.getConnection();
connection.getConnection().addRequestProperty("hea derParameter", "headerValue");
同样的TransportContext
您可以从自定义DefaultSoapHeaderMapper
访问,即使没有任何ThreadLocal
:
@Override
protected void populateUserDefinedHeader(String headerName, Object headerValue, SoapMessage target) {
super.populateUserDefinedHeader(headerName, headerValue, target);
TransportContext context = TransportContextHolder.getTransportContext();
HttpUrlConnection connection = (HttpUrlConnection) context.getConnection();
connection.getConnection().addRequestProperty(headerName, headerValue);
}
谢谢你,阿泰姆。因此,我将继续扩展用于身份验证的HttpComponentsMessageSender
。具有自定义DefaultSoapHeaderMapper
的其他自定义HTTP头,因为它可以访问Message.Headers
。