本文介绍了如何以编程方式设置 JAX-WS 客户端的 SSLContext?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在分布式应用程序中的服务器上工作,该应用程序具有浏览器客户端并参与与第 3 方的服务器到服务器通信.我的服务器有一个 CA 签名的证书,让我的客户端使用 HTTP/S 和 XMPP(安全)使用 TLS (SSL) 通信进行连接.一切正常.

I'm working on a server in a distributed application that has browser clients and also participates in server-to-server communication with a 3rd party.My server has a CA-signed certificate to let my clients connect using TLS (SSL) communication using HTTP/S and XMPP(secure). That's all working fine.

现在我需要通过 HTTPS/SSL 使用 JAX-WS 安全地连接到第 3 方服务器.在此通信中,我的服务器充当 JAX-WS 交互中的客户端,并且我有一个由第 3 方签名的客户端证书.

Now I need to securely connect to a 3rd party server using JAX-WS over HTTPS/SSL. In this communication, my server acts as client in the JAX-WS interation and I've a client certificate signed by the 3rd party.

我尝试通过标准系统配置 (-Djavax.net.ssl.keyStore=xyz) 添加新的密钥库,但我的其他组件显然受此影响.尽管我的其他组件使用专用参数进行 SSL 配置(my.xmpp.keystore=xxx, my.xmpp.truststore=xxy, ...),但似乎它们最终使用了全局SSLContext.(配置命名空间 my.xmpp. 似乎表示分离,但事实并非如此)

I tried adding a new keystore through the standard system configuration (-Djavax.net.ssl.keyStore=xyz) but my other components are clearly affected by this. Although my other components are using dedicated parameters for their SSL configuration (my.xmpp.keystore=xxx, my.xmpp.truststore=xxy, ...), it seems that they end up using the global SSLContext. (The configuration namespace my.xmpp. seemed to indicate separation, but it's not the case)

我也尝试将我的客户端证书添加到我的原始密钥库中,但是 - 同样 - 我的其他组件似乎也不喜欢它.

I also tried adding my client certificate into my original keystore, but -again- my other components don't seem to like it either.

我认为我剩下的唯一选择是以编程方式连接到 JAX-WS HTTPS 配置,以便为客户端 JAX-WS 交互设置密钥库和信任库.

I think that my only option left is to programmatically hook into the JAX-WS HTTPS configuration to setup the keystore and truststore for the client JAX-WS interaction.

关于如何做到这一点的任何想法/指示?我找到的所有信息要么使用 javax.net.ssl.keyStore 方法,要么正在设置全局 SSLContext - 我猜 - 最终会出现在相同的冲突中.我最接近有用的东西是这个旧的错误报告,它要求我需要的功能:添加对将 SSLContext 传递给 JAX-WS 客户端运行时的支持

Any ideas/pointers on how to do this? All information I find either uses the javax.net.ssl.keyStore method or is setting the global SSLContext that -I guess- will end up in the same confilc. The closest I got to something helpful was this old bug report that requests the feature I need: Add support for passing an SSLContext to the JAX-WS client runtime

需要吗?

推荐答案

这是一个难以破解的难题,所以记录一下:

This one was a hard nut to crack, so for the record:

为了解决这个问题,它需要一个自定义的 KeyManager 和一个 SSLSocketFactory 使用这个自定义的 KeyManager 来访问分离的 KeyStore.我在这篇优秀的博客条目中找到了这个 KeyStoreSSLFactory 的基本代码:how-to-dynamically-select-a-certificate-alias-when-invoking-web-services

To solve this, it required a custom KeyManager and a SSLSocketFactory that uses this custom KeyManager to access the separated KeyStore.I found the base code for this KeyStore and SSLFactory on this excellent blog entry:how-to-dynamically-select-a-certificate-alias-when-invoking-web-services

然后,需要将专门的 SSLSocketFactory 插入到 WebService 上下文中:

Then, the specialized SSLSocketFactory needs to be inserted into the WebService context:

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.

Where the getCustomSocketFactory() returns a SSLSocketFactory created using the method mentioned above. This would only work for JAX-WS RI from the Sun-Oracle impl built into the JDK, given that the string indicating the SSLSocketFactory property is proprietary for this implementation.

在此阶段,JAX-WS 服务通信通过 SSL 进行保护,但是如果您从同一个安全服务器 () 加载 WSDL,那么您将遇到引导问题,因为用于收集 WSDL 的 HTTPS 请求将不使用与 Web 服务相同的凭据.我通过使 WSDL 在本地可用(file:///...)并动态更改 Web 服务端点解决了这个问题:(可以找到关于为什么需要这个的很好的讨论 本论坛中)

At this stage, the JAX-WS service communication is secured through SSL, but if you are loading the WSDL from the same secure server () then you'll have a bootstrap problem, as the HTTPS request to gather the WSDL will not be using the same credentials than the Web Service. I worked around this problem by making the WSDL locally available (file:///...) and dynamically changing the web service endpoint: (a good discussion on why this is needed can be found in this forum)

bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, webServiceLocation);

现在 WebService 被引导并且能够使用命名(别名)客户端证书和相互身份验证通过 SSL 与服务器对应物进行通信.∎

Now the WebService gets bootstrapped and is able to communicate through SSL with the server counterpart using a named (alias) Client-Certificate and mutual authentication. ∎

这篇关于如何以编程方式设置 JAX-WS 客户端的 SSLContext?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 07:11