/!\ Updated Page: FrontPage/Axis/DynamicSSLConfig This page contains information about a method for dynamically selecting the client certificate at runtime.

How do I select a client certificate for SSL at run time?

/!\ Note that the SocketFactoryFactory class caches socket factory instances, which stops this working if you really want to change the configuration on the fly. I am using a modified version of SocketFactoryFactory with the caching removed (with a performance hit). But I hope this code may be useful anyway.

If you want more control over the configuration of Axis client SSL, you can use SunJSSESocketFactory as the secure socket factory. SunJSSESocketFactory is a sub-class of JSSESocketFactory. To tell Axis to use this class, create in your classpath, under META-INF/services/ a file called org.apache.axis.components.net.SecureSocketFactory with the content :


To pass the configuration data to the SunJSSESocketFactory at run time, make a custom engine configuration, similar to that described in "How do I setup handlers in Axis clients?".

Here is an example engine configuration which is equivalent to the default client-config.wsdd, with one additional parameter (keystore) for the SSL configuration. The JSSE library always uses the first certificate that it finds in the key store, so this is the way to make it use different certificates for connections to different services. Any option that you set on the HTTPSender is copied, by the Axis code, to the attributes hash table passed to the SunJSSESocketFactory constructor.

import org.apache.axis.AxisEngine;
import org.apache.axis.configuration.SimpleProvider;
import org.apache.axis.EngineConfiguration;
import org.apache.axis.Handler;
import org.apache.axis.SimpleTargetedChain;
import org.apache.axis.transport.http.HTTPSender;
import org.apache.axis.transport.http.HTTPTransport;
import java.util.Hashtable;
    public static EngineConfiguration createClientConfig(String keystoreName) {
        SimpleProvider clientConfig = new SimpleProvider();
        // set global properties to match org/apache/axis/client/client-config.wsdd
        Hashtable opts = new Hashtable();
        opts.put(AxisEngine.PROP_DISABLE_PRETTY_XML, Boolean.TRUE);
        Handler pivot = (Handler) new HTTPSender();
        pivot.setOption("keystore", keystoreName);
        Handler transport = new SimpleTargetedChain(pivot);
        clientConfig.deployTransport(HTTPTransport.DEFAULT_TRANSPORT_NAME, transport);
        return clientConfig;

This engine configuration is used when making the SOAP call as follows (in this example the interface is called GatewaySoapPortal).

    EngineConfiguration engineConfiguration = createClientConfig(myKeystoreName);
    GatewaySoapPortalLocator locator = new GatewaySoapPortalLocator(engineConfiguration);
    ggPortalPortType = locator.getGatewaySoapPortalSoap();

The call to refreshGlobalOptions() is necessary to make the global options (PROP_DISABLE_PRETTY_XML and PROP_ENABLE_NAMESPACE_PREFIX_OPTIMIZATION) take effect. That is the same as what org.apache.axis.configuration.FileProvider does.

Cleaner Solution

A cleaner solution, which avoids the explicit call to refreshGlobalOptions() on every use, would be to make a new class say MyEngineConfig which is a sub-class of SimpleProvider. The createClientConfig() code above goes in the constructor, with modifications. Then override the configureEngine() method so that it calls SimpleProvider.configureEngine() and then calls refreshGlobalOptions(). (This has not been tested, because it was an afterthought.)

    public void configureEngine(AxisEngine engine) throws ConfigurationException

Then the call to get the PortType becomes much simpler:

    ggPortalPortType = new GatewaySoapPortalLocator(
        new MyEngineConfig(myKeystoreName)).getGatewaySoapPortalSoap();

FrontPage/Axis/AxisClientConfiguration/SSLConfig (last edited 2009-09-20 22:48:24 by localhost)