Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 向WS-Outbound网关添加动态HTTP头_Java_Web Services_Spring Integration_Spring Ws - Fatal编程技术网

Java 向WS-Outbound网关添加动态HTTP头

Java 向WS-Outbound网关添加动态HTTP头,java,web-services,spring-integration,spring-ws,Java,Web Services,Spring Integration,Spring Ws,我想使用一些定制的HTTP头来丰富我的HTTP/SOAP请求(使用WS-Outbound Gateway发送),具体取决于消息实际包含的内容,即 为每个请求添加基本身份验证,其中凭据取决于某些消息头 仅当存在特定的消息头时添加自定义HTTP头 我考虑了以下解决办法: 实现自定义ClientInterceptor——但无法访问 此时的Message.header 实现定制的SoapHeaderMapper——可以访问Message.header,但我不喜欢这个想法,因为它的意思是 在SOAP信

我想使用一些定制的HTTP头来丰富我的HTTP/SOAP请求(使用WS-Outbound Gateway发送),具体取决于
消息
实际包含的内容,即

  • 为每个请求添加基本身份验证,其中凭据取决于某些
    消息头
  • 仅当存在特定的
    消息头时添加自定义HTTP头
我考虑了以下解决办法:

  • 实现自定义
    ClientInterceptor
    ——但无法访问 此时的Message.header
  • 实现定制的
    SoapHeaderMapper
    ——可以访问
    Message.header
    ,但我不喜欢这个想法,因为它的意思是 在SOAP信封上操作,而不是在连接/请求级别
  • 实现自定义
    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;
    }
    }
    
    
    公共类BasicAuthenticationMessageSender扩展了HttpComponents消息Sender{
    私有静态ThreadLocal httpClientContextLocal=新ThreadLocal();
    @凌驾
    受保护的HttpContext createContext(URI){
    HttpClientContext HttpClientContext=httpClientContextLocal.get();
    //这一部分使身份验证优先:
    HttpHost targetHost=新的HttpHost(uri.getHost(),uri.getPort(),uri.getScheme());
    AuthCache AuthCache=new BasicAuthCache();
    put(targetHost,newbasicscheme());
    httpClientContext.setAuthCache(authCache);
    返回httpClientContext;
    }
    公共GenericMessage setBasicAuth(GenericMessage消息、字符串用户名、字符串密码)引发异常{
    最终的HttpClientContext HttpClientContext=HttpClientContext.create();
    CredentialsProvider CredentialsProvider=新的BasicCredentialsProvider();
    setCredentials(AuthScope.ANY,新用户名密码Credentials(用户名,密码));
    httpClientContext.setCredentialsProvider(credentialsProvider);
    httpClientContextLocal.set(httpClientContext);
    返回消息;
    }
    }
    

    Spring集成4.3.11

    没错。因为SpringIntegrationWS支持完全基于SpringWS项目,所以我们在SI中不能再看到SWS为我们提供的东西了

    无论如何,您可以将
    WebServiceMessageCallback
    注入
    AbstractWebServiceOutboundGateway
    中,在调用此WS-Gateway之前,可以访问填充在此处的
    消息的
    ThreadLocal
    变量

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

    谢谢你,阿泰姆。因此,我将继续扩展用于身份验证的
    HttpComponentsMessageSender
    。具有自定义
    DefaultSoapHeaderMapper
    的其他自定义HTTP头,因为它可以访问
    Message.Headers