2017-08-05 54 views
1

我想豐富自己的HTTP/SOAP請求(與WS出站網關發送)與根據一些自定義HTTP頭什麼實際Message包含,即添加動態HTTP標頭WS出站網關

  • 增加基本身份驗證每個請求,其中憑證依賴於某些Message.headers
  • 添加自定義HTTP標頭只有特定Message.headers存在

我考慮了以下解決方案:

  1. 實現自定義ClientInterceptor - 但目前還 Message.header用不上此時
  2. 實現自定義SoapHeaderMapper - 就有機會獲得Message.header,但我不喜歡這個主意,因爲它是相當意味着 進行操作SOAP信封不在連接/請求級別。
  3. 實現自定義WebServiceMessageCallback - 此時無法訪問消息。

此外,在身份驗證的情況下,上述所有解決方案依賴於我們自己添加必要的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集成4.3.11

回答

1

這是正確的。由於Spring集成WS支持完全基於Spring WS項目,因此我們無法在SI中爲SWS提供什麼。

無論如何,您可以將WebServiceMessageCallback注入AbstractWebServiceOutboundGateway,並且在調用此WS網關之前,可以訪問MessageThreadLocal變量。

有在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); 
} 
+0

由於阿爾喬姆。所以我會繼續擴展用於認證的'HttpComponentsMessageSender'。其他具有自定義'DefaultSoapHeaderMapper'的自定義HTTP頭,因爲它可以訪問'Message.headers'。 – kulas