我想通过一些自定义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之前可以访问其中填充的ThreadLocalMessage变量。

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/

10-12 03:04