我想使用一些自定义 HTTP header 来丰富我的 HTTP/SOAP 请求(使用 WS 出站网关发送),具体取决于 Message
实际包含的内容,即
- 为每个请求添加基本身份验证,其中凭据取决于某些
Message.headers
- 仅当特定
Message.headers
存在时才添加自定义 HTTP header
我考虑了以下解决方案:
- 实现自定义
ClientInterceptor
- 但无法访问 此时的Message.header - 实现自定义
SoapHeaderMapper
- 可以访问Message.header
但我不喜欢这个想法,因为它是有意义的 在 SOAP 信封上操作,而不是在连接/请求级别上操作。 - 实现自定义
WebServiceMessageCallback
- 此时无法访问消息。
此外,在身份验证的上下文中,上述所有解决方案都依赖于我们自己添加必要的 HTTP 身份验证 header ,而我想以更正确的方式(至少在我看来)做到这一点并正确配置 HttpClient
.
因此,此时我完成了为每个请求设置 HttpClientContext
的自定义 HttpComponentsMessageSender
。问题是,再次无法访问 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 集成 4.3.11
最佳答案
没错。由于 Spring Integration WS 支持完全基于 Spring WS 项目,因此我们在 SI 中无法提供 SWS 为我们提供的更多内容。
无论如何,您可以将WebServiceMessageCallback
注入(inject)AbstractWebServiceOutboundGateway
,然后访问Message
的ThreadLocal
变量在调用此 WS 网关之前填充在那里。
在 WebServiceMessageCallback
中,您应该可以访问:
TransportContext context = TransportContextHolder.getTransportContext();
HttpUrlConnection connection = (HttpUrlConnection) context.getConnection();
connection.getConnection().addRequestProperty("hea derParameter", "headerValue");
您可以从自定义 DefaultSoapHeaderMapper
访问相同的 TransportContext
,即使没有任何 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/