java - 将动态 HTTP header 添加到 WS 出站网关

标签 java web-services spring-integration spring-ws

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

  • 为每个请求添加基本身份验证,其中凭据取决于某些 Message.headers
  • 仅当特定 Message.headers 存在时才添加自定义 HTTP header

我考虑了以下解决方案:

  1. 实现自定义ClientInterceptor - 但无法访问 此时的Message.header
  2. 实现自定义 SoapHeaderMapper - 可以访问 Message.header 但我不喜欢这个想法,因为它是有意义的 在 SOAP 信封上操作,而不是在连接/请求级别上操作。
  3. 实现自定义 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,然后访问MessageThreadLocal变量在调用此 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/

相关文章:

Java:从 wsdl 获取示例请求 XML

java - 是否可以将 EVAL SHA 与 spring-data redis 一起使用?

java - 与 jdk indexOf() 相比,GWT 模拟的 indexOf() 不正确

java - 创建自定义 Web 应用程序上下文 [SPRING]

Java JComponent.getGraphics() 始终返回 null

java - 无法在 Axis2 客户端项目中加载 Rampart 模块

web-services - Spring restTemplate.postForEntity(或 postForObject)在独立 Java 应用程序中给出错误 "no suitable HttpMessageConverter"

java - Spring Integration WebFlux.outboundGateway 永远不会被调用

java - Spring集成Kafka