maa*_*asg 54 java ssl certificate jax-ws
我正在一个分布式应用程序中的服务器上工作,该应用程序具有浏览器客户端,并且还参与与第三方的服务器到服务器通信.我的服务器有一个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, ...),但似乎他们最终使用全局SSLContext.(配置命名空间my.xmpp.似乎表示分离,但事实并非如此)
我也尝试将我的客户端证书添加到我的原始密钥库中,但是 - 我的其他组件似乎也不喜欢它.
我认为我唯一的选择是以编程方式挂钩到JAX-WS HTTPS配置,以便为客户端JAX-WS交互设置密钥库和信任库.
关于如何做到这一点的任何想法/指示?我找到的所有信息要么使用该javax.net.ssl.keyStore方法,要么设置全局SSLContext- 我猜 - 将最终在同一个confilc中.我得到的最接近的东西是这个旧的错误报告请求我需要的功能:添加支持将SSLContext传递给JAX-WS客户端运行时
任何需要?
maa*_*asg 55
这个是一个难以破解的难题,所以为了记录:
要解决此问题,它需要一个自定义KeyManager和一个SSLSocketFactory使用此自定义KeyManager来访问分离的自定义KeyStore.我发现基码本KeyStore和SSLFactory对这个优秀的博客条目:
如何对动态选择-一个证书别名时,调用的Web服务
然后,SSLSocketFactory需要将特殊插入到WebService上下文中:
service = getWebServicePort(getWSDLLocation());
BindingProvider bindingProvider = (BindingProvider) service;
bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", getCustomSocketFactory());
Run Code Online (Sandbox Code Playgroud)
使用上述方法创建的getCustomSocketFactory()返回值SSLSocketFactory.这仅适用于内置于JDK中的Sun-Oracle impl的JAX-WS RI,因为指示该SSLSocketFactory属性的字符串是此实现的专有权.
在此阶段,JAX-WS服务通信通过SSL加以保护,但如果您从同一安全服务器()加载WSDL,那么您将遇到引导问题,因为收集WSDL的HTTPS请求将不会使用与Web Service相同的凭据.我通过使WSDL在本地可用(file:/// ...)并动态更改Web服务端点来解决这个问题:( 在此论坛中可以找到关于为什么需要这个的好讨论)
bindingProvider.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, webServiceLocation);
Run Code Online (Sandbox Code Playgroud)
现在WebService被引导并且能够使用命名(别名)客户端证书和相互身份验证通过SSL与服务器对应方进行通信.∎
小智 21
这是我根据这篇文章通过一些小调整解决它的方法.此解决方案不需要创建任何其他类.
SSLContext sc = SSLContext.getInstance("SSLv3");
KeyManagerFactory kmf =
KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm() );
KeyStore ks = KeyStore.getInstance( KeyStore.getDefaultType() );
ks.load(new FileInputStream( certPath ), certPasswd.toCharArray() );
kmf.init( ks, certPasswd.toCharArray() );
sc.init( kmf.getKeyManagers(), null, null );
((BindingProvider) webservicePort).getRequestContext()
.put(
"com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory",
sc.getSocketFactory() );
Run Code Online (Sandbox Code Playgroud)
小智 20
我尝试了以下内容,但它对我的环境无效:
bindingProvider.getRequestContext().put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", getCustomSocketFactory());
Run Code Online (Sandbox Code Playgroud)
但不同的财产就像一个魅力:
bindingProvider.getRequestContext().put(JAXWSProperties.SSL_SOCKET_FACTORY, getCustomSocketFactory());
Run Code Online (Sandbox Code Playgroud)
其余代码取自第一个回复.
通过结合 Radek 和 l0co 的答案,您可以访问 https 后面的 WSDL:
SSLContext sc = SSLContext.getInstance("TLS");
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(getClass().getResourceAsStream(keystore),
password.toCharArray());
kmf.init(ks, password.toCharArray());
sc.init(kmf.getKeyManagers(), null, null);
HttpsURLConnection
.setDefaultSSLSocketFactory(sc.getSocketFactory());
yourService = new YourService(url); //Handshake should succeed
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
121959 次 |
| 最近记录: |