我想通过一些自定义HTTP标头来丰富我的HTTP / SOAP请求(随WS Outbound Gateway发送),具体取决于Message
实际包含的内容,即
每个请求都添加基本身份验证,其中凭据取决于某些Message.headers
仅在存在特定的Message.headers
时添加自定义HTTP标头
我考虑了以下解决方案:
实施自定义ClientInterceptor
-但无法访问
此时的Message.header
实现自定义SoapHeaderMapper
-可以访问Message.header
,但是我不喜欢这个想法,因为它的意思是
在SOAP信封上而不是在连接/请求级别上进行操作。
实施自定义WebServiceMessageCallback
-目前无法访问Message。
另外,在身份验证的上下文中,所有上述解决方案都依靠我们自己添加必要的HTTP身份验证标头,而我想以更正确的方式(至少在我看来)这样做并正确配置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;
}
}
Spring Integration 4.3.11
最佳答案
那就对了。由于Spring Integration WS的支持完全基于Spring WS项目,因此在SI中我们再也无法提供SWS为我们提供的服务。
无论如何,您都可以将WebServiceMessageCallback
注入AbstractWebServiceOutboundGateway
中,并在调用此WS Gateway之前可以访问其中填充的ThreadLocal
的Message
变量。
在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);
}
关于java - 将动态HTTP header 添加到WS出站网关,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45520153/