我正在使用具有浏览器客户端的分布式应用程序中的服务器,并且还参与了与第三方的服务器到服务器通信。我的服务器具有CA签名的证书,可让我的客户端使用HTTP / S和XMPP(安全)通过TLS(SSL)通信进行连接。一切都很好。
现在,我需要通过HTTPS / SSL使用JAX-WS安全地连接到第三方服务器。在此通信中,我的服务器在JAX-WS交互中充当客户端,并且我有一个由第三方签名的客户端证书。
我尝试通过标准系统配置(-Djavax.net.ssl.keyStore=xyz)添加新的密钥库,但是其他组件显然受此影响。尽管我的其他组件正在对其SSL配置(my.xmpp.keystore=xxx, my.xmpp.truststore=xxy, ...)使用专用参数,但看来它们最终还是使用global SSLContext。(配置名称空间my.xmpp.似乎指示分离,但事实并非如此)
(my.xmpp.keystore=xxx, my.xmpp.truststore=xxy, ...
global SSLContext
我还尝试将客户证书添加到原始密钥库中,但是-同样,我的其他组件似乎也不喜欢它。
我认为我剩下的唯一选择是以编程方式挂接到JAX-WS HTTPS配置中,以设置客户端JAX-WS交互的密钥库和信任库。
关于如何执行此操作的任何想法/指标?我发现的所有信息都使用该javax.net.ssl.keyStore方法或设置了SSLContext-我猜想-最终将在同一配置文件中使用的全局信息。与我最接近的有用信息是这个旧的错误报告,该报告要求我需要的功能:添加对将SSLContext传递到JAX-WS客户端运行时的支持
SSLContext
有需要吗?
这是一个很难破解的坚果,因此记录如下:
要解决此问题,它需要一个自定义,KeyManager并SSLSocketFactory使用此自定义KeyManager访问的分隔符KeyStore。我发现基码本KeyStore和SSLFactory对这个优秀的博客条目: 如何对动态选择-一个证书别名时,调用的Web服务
KeyManager
SSLSocketFactory
然后,SSLSocketFactory需要将专门的插入到WebService上下文中:
service = getWebServicePort(getWSDLLocation()); BindingProvider bindingProvider = (BindingProvider) service; bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", getCustomSocketFactory());
当getCustomSocketFactory()返回一个SSLSocketFactory使用该方法产生如上所述。假定指示该SSLSocketFactory属性的字符串是此实现专有的,那么这仅适用于JDK中内置的Sun-Oracle impl的JAX-WS RI 。
在此阶段,通过SSL保护JAX-WS服务通信的安全,但是如果您从同一安全服务器()加载WSDL,则将遇到引导程序问题,因为将不会使用HTTPS收集WSDL的请求与Web服务相同的凭据。我通过使WSDL在本地可用(file:/// …)并动态更改Web服务端点来解决了这个问题:(可以在此论坛中找到有关为什么需要这样做的很好的讨论)
bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, webServiceLocation);
现在,WebService已启动,并可以使用命名的(别名)客户端证书和相互身份验证通过SSL与服务器副本进行通信。