如何在 CXF 导管上设置 TLS 参数?
How to set TLS parameters on a CXF conduit?
我的应用程序有两个传出 SOAP 连接。对于那些,我想实施 TLS。两者都是使用 CXF 创建的。
javax.xml.ws.Service.getPort()
returns 一个单独的 bindingProvider(两个连接都使用它们自己的 WSDL)但都使用相同的 org.apache.cxf.bus.spring.SpringBus
实例。
在使用 bindingProvider 之前,我在 Conduit 上设置了 TLS 客户端参数:
Client client = ClientProxy.getClient(bindingProvider); // different
HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); // same for both connections
TLSClientParameters tlsClientParameters = new TLSClientParameters();
tlsClientParameters.setTrustManagers(getTrustmanagers());
httpConduit.setTlsClientParameters(tlsClientParameters);
问题是,两个连接检索到的客户端不同,但管道是同一个对象。因此,当我为同一个对象设置第二个连接的参数时,我覆盖了之前设置的设置。
FAQ 的回答 if CXF is threadsafe 为“是”,但有一些例外。我认为第二个例外适用于此。它说:
CXF answer: CXF proxies are thread safe for MANY use cases. The exceptions are:
[...]
Settings on the conduit - if you use code or configuration to directly manipulate the conduit (like to set TLS settings or similar), those are not thread safe. The conduit is per-instance and thus those settings would be shared. Also, if you use the FailoverFeature and LoadBalanceFeatures, the conduit is replaced on the fly. Thus, settings set on the conduit could get lost before being used on the setting thread.
[...]
For the conduit issues, you COULD install a new ConduitSelector that uses a thread local or similar. That's a bit complex though.
我不完全确定线程安全是否是我的问题。我在各自的组件中创建了两个连接。 Springs 仅使用一个线程来初始化所有组件,因此两个连接都由同一个线程初始化。但之后,连接使用池中的线程。覆盖设置发生在初始化期间,因此在使用不同线程发送实际 SOAP 消息之前。
当在 org.apache.cxf.endpoint.AbstractConduitSelector#getSelectedConduit
中创建管道时,它是使用 SpringBus
完成的,这两个对象是相同的实例。
因此,常见问题解答告诉我使用我自己的自定义 ConduitSelector。
我尝试在上面的初始化之前设置它:
Client client = ClientProxy.getClient(bindingProvider);
client.setConduitSelector(
new UpfrontConduitSelector(
new URLConnectionHTTPConduit(client.getBus(),
client.getEndpoint().getEndpointInfo())));
我在初始化后也尝试了同样的方法。在这两种情况下,在设置管道选择器之后,当某些东西使用 BindingProvider(它是一个代理对象)时,它会得到一个 NullPointerException,尽管该对象不为空。
我的问题是获取自定义管道选择器 运行 或查看我的问题是否可以完全不同地解决,或者只是为了获得一些灵感:)
SO 上的某个人似乎已经解决了这个问题 here,但他的问题的答案对我没有帮助。
我找到了解决方案。
这个问题确实与多线程无关,但与 SpringBus 连接到我的对象的方式以及如何从中创建 Conduit 有关。
解决方案是为每个服务提供自己的 SpringBus。
因此,在我通过在 javax.xml.ws.Service
中调用它的 c'tor 创建每个 SOAP 服务之前,我会
BusFactory bf = BusFactory.newInstance();
Bus b = bf.createBus();
BusFactory.setThreadDefaultBus(b);
设置一个新的线程局部默认总线,然后用于创建的服务。因此,我的两个服务都有自己的 SpringBus,并且都创建了自己的 Conduit。
这是可行的,因为每个服务都是一个 spring @Component
并且所有 spring 组件都是由主线程创建的。所以只有一个线程,这段代码不可能不顺序执行。
我的应用程序有两个传出 SOAP 连接。对于那些,我想实施 TLS。两者都是使用 CXF 创建的。
javax.xml.ws.Service.getPort()
returns 一个单独的 bindingProvider(两个连接都使用它们自己的 WSDL)但都使用相同的 org.apache.cxf.bus.spring.SpringBus
实例。
在使用 bindingProvider 之前,我在 Conduit 上设置了 TLS 客户端参数:
Client client = ClientProxy.getClient(bindingProvider); // different
HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); // same for both connections
TLSClientParameters tlsClientParameters = new TLSClientParameters();
tlsClientParameters.setTrustManagers(getTrustmanagers());
httpConduit.setTlsClientParameters(tlsClientParameters);
问题是,两个连接检索到的客户端不同,但管道是同一个对象。因此,当我为同一个对象设置第二个连接的参数时,我覆盖了之前设置的设置。
FAQ 的回答 if CXF is threadsafe 为“是”,但有一些例外。我认为第二个例外适用于此。它说:
CXF answer: CXF proxies are thread safe for MANY use cases. The exceptions are:
[...]
Settings on the conduit - if you use code or configuration to directly manipulate the conduit (like to set TLS settings or similar), those are not thread safe. The conduit is per-instance and thus those settings would be shared. Also, if you use the FailoverFeature and LoadBalanceFeatures, the conduit is replaced on the fly. Thus, settings set on the conduit could get lost before being used on the setting thread.
[...]
For the conduit issues, you COULD install a new ConduitSelector that uses a thread local or similar. That's a bit complex though.
我不完全确定线程安全是否是我的问题。我在各自的组件中创建了两个连接。 Springs 仅使用一个线程来初始化所有组件,因此两个连接都由同一个线程初始化。但之后,连接使用池中的线程。覆盖设置发生在初始化期间,因此在使用不同线程发送实际 SOAP 消息之前。
当在 org.apache.cxf.endpoint.AbstractConduitSelector#getSelectedConduit
中创建管道时,它是使用 SpringBus
完成的,这两个对象是相同的实例。
因此,常见问题解答告诉我使用我自己的自定义 ConduitSelector。 我尝试在上面的初始化之前设置它:
Client client = ClientProxy.getClient(bindingProvider);
client.setConduitSelector(
new UpfrontConduitSelector(
new URLConnectionHTTPConduit(client.getBus(),
client.getEndpoint().getEndpointInfo())));
我在初始化后也尝试了同样的方法。在这两种情况下,在设置管道选择器之后,当某些东西使用 BindingProvider(它是一个代理对象)时,它会得到一个 NullPointerException,尽管该对象不为空。
我的问题是获取自定义管道选择器 运行 或查看我的问题是否可以完全不同地解决,或者只是为了获得一些灵感:)
SO 上的某个人似乎已经解决了这个问题 here,但他的问题的答案对我没有帮助。
我找到了解决方案。
这个问题确实与多线程无关,但与 SpringBus 连接到我的对象的方式以及如何从中创建 Conduit 有关。
解决方案是为每个服务提供自己的 SpringBus。
因此,在我通过在 javax.xml.ws.Service
中调用它的 c'tor 创建每个 SOAP 服务之前,我会
BusFactory bf = BusFactory.newInstance();
Bus b = bf.createBus();
BusFactory.setThreadDefaultBus(b);
设置一个新的线程局部默认总线,然后用于创建的服务。因此,我的两个服务都有自己的 SpringBus,并且都创建了自己的 Conduit。
这是可行的,因为每个服务都是一个 spring @Component
并且所有 spring 组件都是由主线程创建的。所以只有一个线程,这段代码不可能不顺序执行。