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

时间:2017-08-05 09:05:00

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

我想根据实际Message包含的内容来丰富我的HTTP / SOAP请求(使用WS Outbound Gateway发送)和一些自定义HTTP标头,即

  • 为每个请求添加基本身份验证,其中凭据取决于某些Message.headers
  • 仅在特定Message.headers存在的情况下添加自定义HTTP标头

我考虑了以下解决方案:

  1. 实施自定义ClientInterceptor - 但无法访问 此时的Message.header
  2. 实施自定义SoapHeaderMapper - 可以访问Message.header,但我不喜欢这个想法,因为它意味着 在SOAP信封上操作而不是在连接/请求级别上操作。
  3. 实现自定义WebServiceMessageCallback - 此时无权访问Message。
  4. 此外,在身份验证的上下文中,所有上述解决方案都依赖于我们自己添加必要的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

1 个答案:

答案 0 :(得分:1)

那是对的。由于Spring Integration WS支持完全基于Spring WS项目,因此我们无法在SI中为SWS提供什么。

无论如何,您可以将WebServiceMessageCallback注入AbstractWebServiceOutboundGateway,然后在调用此WS网关之前,可以访问填充在那里的ThreadLocal的{​​{1}}变量。

Message您应该访问:

WebServiceMessageCallback

您可以从自定义TransportContext context = TransportContextHolder.getTransportContext(); HttpUrlConnection connection = (HttpUrlConnection) context.getConnection(); connection.getConnection().addRequestProperty("hea derParameter", "headerValue"); 访问相同的TransportContext,甚至已经没有任何DefaultSoapHeaderMapper

ThreadLocal