将动态 HTTP Headers 添加到 WS 出站网关

Adding dynamic HTTP Headers to WS Outbound Gateway

我想使用一些自定义 HTTP Headers 来丰富我的 HTTP/SOAP 请求(使用 WS 出站网关发送),具体取决于 Message 实际包含的内容,即

我考虑了以下解决方案:

  1. 正在实施自定义 ClientInterceptor - 但无法访问 Message.header此时
  2. 实施自定义 SoapHeaderMapper - 可以访问 Message.header 但我不喜欢这个想法,因为它本来就是 在 SOAP 信封上操作,而不是在 connection/request 级别上操作。
  3. 正在实施自定义 WebServiceMessageCallback - 此时无法访问 Message。

此外,在身份验证的上下文中,上述所有解决方案都依赖于我们自己添加必要的 HTTP 身份验证 header,而我想以更正确的方式进行(至少在我看来)并且正确配置 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 集成 4.3.11

没错。由于 Spring 集成 WS 支持完全基于 Spring WS 项目,因此在 SI 中我们无法再使用 SWS 为我们提供的内容。

无论如何,您可以将 WebServiceMessageCallback 注入 AbstractWebServiceOutboundGateway 并在调用此 WS 网关之前访问 Message 填充的 ThreadLocal 变量。

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