即时修改的CXF故障转移管道-确保相同的SSL会话和客户端线程安全性?

问题描述 投票:0回答:1

我想为我们的应用程序中的两个JAX-WS / RS客户端实现CXF的故障转移功能,这些客户端必须使用客户端证书通过HTTPS调用远程Web服务。 2台远程服务器到位:主服务器+备用服务器。

发生故障转移后,如何保证相同的功能(具有正确的TLS参数/ SSL会话),我有点困惑。

[JAX-WS客户端

有6个ClientService,它们extend AbstractClientServiceImpl并使用相同的PortType wsClient bean和远程服务器的相同basePath,但是它们使用自己的String getEndpointUrl(){ return "X";}方法将其设置为被调用服务的最后uri部分。

BasePath:https://remote1.server.com:443/api

备用地址:https://remote2.server.com:443/api

[请查看代码-ClientEndpointAddressInterceptor。使用此拦截器,即使发生故障转移,我也可以组合basePath + lastUriPart并为特定的ClientService调用适当的目标端点。例如:

ClientService1.class https://remote1.server.com:443/api/service1的目标端点”>

ClientService2.class的目标端点:https://remote1.server.com:443/api/service2

我一直在为正确的设置/配置苦苦挣扎2周。如果我没有像这样将tlsClientParameters或HttpClientPolicy添加到extensor

,那么在[发生故障转移后,我将无法看到新创建的管道的任何TLS设置!// ssl settings endpointInfo.addExtensor(tlsClientParameters);
我不知道这是否是正确的方法,但是有了这种变通的解决方法,我可以为2个远程调用(主要+备用远程服务器地址)“提供”相同的

tlsClientParams

)-客户端证书的SAN具有两个服务器的DNS名称。
技术:SpringBoot v2.1 + CXF 3.3.0 + Tomcat8.5

@Bean public PortType wsClient(Properties properties, TLSClientParameters tlsClientParameters, LoggingFeature loggingFeature, ClientEndpointAddressFeature clientEndpointAddressFeature) { return createClient(properties, huTlsClientParameters, loggingFeature, createFailoverFeature(properties.getFailover().getAddresses(), properties.getFailover().getRetryDelay()), clientEndpointAddressFeature); } private FailoverFeature createFailoverFeature(String[] alternateAddresses, long failOverRetryDelay) { final FailoverFeature failOverFeature = new FailoverFeature(); final SequentialStrategy strategy = new SequentialStrategy(); strategy.setAlternateAddresses(Arrays.asList(alternateAddresses)); strategy.setDelayBetweenRetries(failOverRetryDelay); failOverFeature.setStrategy(strategy); return failOverFeature; } private PortType createClient(Properties properties, TLSClientParameters tlsClientParameters, WebServiceFeature... features) { final Service service = new Service(); final PortType client = service.getPortType(features); final Client clientProxy = ClientProxy.getClient(client); final EndpointInfo endpointInfo = clientProxy.getEndpoint().getEndpointInfo(); final HTTPClientPolicy httpClientPolicy = Optional.ofNullable(endpointInfo.getExtensor(HTTPClientPolicy.class)) .orElseGet(() -> { // if there is no XYFeature, policy has to be initialized at this point final HTTPClientPolicy policy = new HTTPClientPolicy(); policy.setAccept(HuHttpHeaders.HEADER_ACCEPT_VALUE); endpointInfo.addExtensor(policy); return policy; }); // timeout settings httpClientPolicy.setConnectionTimeout(properties.getConnectionTimeout()); httpClientPolicy.setReceiveTimeout(properties.getReadTimeout()); // set content-length by default httpClientPolicy.setAllowChunking(false); // ssl settings endpointInfo.addExtensor(tlsClientParameters); // set global requestContext setRequestContext((BindingProvider) client, properties.getUrl()); return client; } private void setRequestContext(BindingProvider bp, String server) { bp.getRequestContext().put(Message.ENDPOINT_ADDRESS, server); bp.getRequestContext().put(ClientImpl.THREAD_LOCAL_REQUEST_CONTEXT, true); bp.getRequestContext().put(Message.SCHEMA_VALIDATION_ENABLED, true); bp.getRequestContext().put(BindingProvider.SOAPACTION_USE_PROPERTY, true); } public class ClientEndpointAddressOutInterceptor extends AbstractPhaseInterceptor<Message> { public ClientEndpointAddressOutInterceptor() { super(Phase.PREPARE_SEND); addBefore(MessageSenderInterceptor.class.getName()); } @Override public void handleMessage(Message message) throws Fault { final String previousEndpointAddress = (String) message.get(Message.ENDPOINT_ADDRESS); final String lastUriPath = (String) message.get("lastUriPath"); message.put(Message.ENDPOINT_ADDRESS, previousEndpointAddress + lastUriPath); } } public abstract class AbstractClientServiceImpl implements ClientService { public AbstractClientServiceImpl(PortType PortType) { this.portType = portType; } @Override public HttpStatus sendRequest(String xmlData) { ... final BindingProvider bindingProvider = (BindingProvider) this.portType; try { // set http header for this particular request // also store bindingProvider.getRequestContext().put("lastUriPath", getEndpointUrl()); HttpHeaderUtil.setHttpHeader(getSoapActionUrl(), bindingProvider, getEndpointUrl()); execute(xmlData, createSoapHeader()); } catch (Exception ex) { ... } ... } // last uri part protected abstract String getEndpointUrl(); // execute is responsible for calling a particular service. e.g: in ClientService1.class portType.callService1(xmlData); protected abstract void execute(String xmlData, TransactionHeader transactionHeader); }

问题

[JAX-WS客户端

    故障转移发生后,先前设置的(thread-local-requests,true)设置会发生什么情况?之后,由6 ClientServices类调用的以下服务调用是否仍将保持线程安全?
  • 我必须使用SSL会话重用机制。如果CXF的故障转移功能删除了管道并创建了一个新管道,那么如何在故障转移后再次应用该管道?还是Tomcat以某种方式处理了这个问题,而无需理会呢?我不是CXF专家,我在CXF的站点/邮件列表中找不到很多与SSL会话相关的信息。
  • [JAX-RS客户端

实际上与上面针对JAX-WS客户端解决的2个关注/问题相同。

唯一的区别是,RS使用声明为]的相同客户端实例具有3个客户端调用方法>

private WebClient webClient(){ final JAXRSClientFactoryBean clientFactoryBean = new JAXRSClientFactoryBean(); clientFactoryBean.setThreadSafe(true); final WebClient webClient = clientFactoryBean.createWebClient(); final ClientConfiguration config = WebClient.getConfig(webClient); config.getRequestContext().put(HTTPConduit.NO_IO_EXCEPTIONS, Boolean.TRUE); // ssl settings config.getEndpoint().getEndpointInfo().addExtensor(tlsClientParameters); return webClient; }

谢谢您的帮助。

我想为我们的应用程序中的两个JAX-WS / RS客户端实现CXF的故障转移功能,这些客户端必须使用客户端证书通过HTTPS调用远程Web服务。已安装2台远程服务器:...

java spring-boot ssl tomcat cxf
1个回答
0
投票
解决方案是使用CXF的HTTPConduitConfigurator,如此处所述:https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=49941#ClientHTTPTransport(includingSSLsupport)-HowtouseHTTPConduitConfigurer

HTTPConduitConfigurer httpConduitConfigurer = new HTTPConduitConfigurer() { public void configure(String name, String address, HTTPConduit c) { c.setTlsClientParameters(_tlsParams); } } bus.setExtension(httpConduitConfigurer, HTTPConduitConfigurer.class);

© www.soinside.com 2019 - 2024. All rights reserved.