Full control of client and server certificates with a JBossW
yhrn Jan 16, 2008 9:57 AMHi,
I want to invoke a web service over https with client certificate authentication. The problem is that I need to control exactly which client certificate/key is used and what server certificates to trust per invocation. All examples i can find involves setting global properties and that is not good enough for me.
My application is an EJB3 application running in in JBoss AS 4.2.2 with JBossWS as JAX-WS provider. In JAX-WS 2.1 RI there is a simple way of doing what I want by setting a passing a SSLSocketFactory in the RequestContext of the SEI proxy (see my example below).
package org.acme.ejb3; import java.net.Socket; import java.security.Principal; import java.security.PrivateKey; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Map; import javax.ejb.Remote; import javax.ejb.Stateless;import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509KeyManager; import javax.net.ssl.X509TrustManager; import javax.xml.ws.BindingProvider; import javax.xml.ws.WebServiceRef; @Stateless @Remote(MyTestClient.class) public class MyTestClientBean implements MyTestClient { @WebServiceRef(SomeWebService.class) private SomeWebServicePortType sei; @Override public String saySometing(String message, String endpointAddress, X509Certificate[] clientCertChain, PrivateKey clientKey, X509Certificate trustedCaCert) throws Exception { Map<String, Object> reqCtx = ((BindingProvider)sei).getRequestContext(); // Standard JAX-WS method to set the endpoint address. reqCtx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointAddress); // My custom key manager KeyManager[] keyMgrs = { new MyClientKeyManager(clientCertChain, clientKey) }; // My custom trust manager TrustManager[] trustMgrs = { new MyClientTrustManager(trustedCaCert) }; // Get an SSL context and initialize it with my custom key and trust managers. SSLContext sslCtx = SSLContext.getInstance("TLS"); sslCtx.init(keyMgrs, trustMgrs, SecureRandom.getInstance("SHA1PRNG")); // Use the JAX-WS 2.1 RI specific property to ensure that // my custom managers are used. reqCtx.put(com.sun.xml.ws.developer.JAXWSProperties.SSL_SOCKET_FACTORY, sslCtx.getSocketFactory()); // Finally invoke the web service. return sei.saySometing(message); } } class MyClientKeyManager implements X509KeyManager { private X509Certificate[] clientCertChain; private PrivateKey clientKey; public MyClientKeyManager(X509Certificate[] clientCertChain, PrivateKey clientKey) { this.clientCertChain = clientCertChain; this.clientKey = clientKey; } // Here comes my custom KeyManager implementation } class MyClientTrustManager implements X509TrustManager { private X509Certificate trustedCaCertificate; public MyClientTrustManager(X509Certificate trustedCaCertificate) { this.trustedCaCertificate = trustedCaCertificate; } // Here comes my custom TrustManager implementation }
Is there any way of doing something similar in JBossWS?