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.
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.
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.
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.
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
Any takes?
This one was a hard nut to crack, so for the record:
To solve this, it required a custom
KeyManagerand aSSLSocketFactorythat uses this customKeyManagerto access the separatedKeyStore.I found the base code for this
KeyStoreandSSLFactoryon this excellent blog entry:how-to-dynamically-select-a-certificate-alias-when-invoking-web-services
Then, the specialized
SSLSocketFactoryneeds to be inserted into the WebService context:Where the
getCustomSocketFactory()returns aSSLSocketFactorycreated 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 theSSLSocketFactoryproperty is proprietary for this implementation.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)
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. ∎