I have some application that need to run in the same Application server. Each application need to authenticate through the same web service using a certificate specific for that application. Obviously I can put all the certificates inside the same keystore, but how can I specify which one I have to use? For the calls I'm using a Spring WebServiceTemplate and I want to find something that can be easily configure inside the spring xml configuration file.
I'm trying to follow this: How can I have multiple SSL certificates for a Java server
The whole concept is clear but I can't understand how to link it with Spring WebServiceTemplate and how to specify inside the call which certificate I have to use.
There is a much easier approach rather than using a custom HTTP Client factory bean that manually sets up the SSL context and uses interceptors to remove the content length headers (little Hokie if you ask me).
Spring has a HttpsUrlConnectionMessageSender that will automatically setup the SSLContext correctly and allow you to specify different keystore and truststore via the KeyStoreManager and TrustStoreManager. This approach makes it much cleaner to do mutual SSL authentication from the client side.
public class MyWebServiceClient extends WebServiceGatewaySupport implements MyWebServicePortType {
@Configuration
public static class MyClientConfig {
@Value("${myws.endpoint.url}")
private String url;
@Value("${myws.keystore}")
private Resource keyStore;
@Value("${myws.keystore.password}")
private String keyStorePass;
@Value("${myws.truststore}")
private Resource trustStore;
@Value("${myws.truststore.password}")
private String trustStorePass;
@Bean
public Jaxb2Marshaller myWebServiceClientMarshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("com.myws.types");
return marshaller;
}
@Bean
public MyWebServiceClient myWebServiceClient() throws Exception {
MyWebServiceClient client = new MyWebServiceClient();
client.setDefaultUri(this.url);
client.setMarshaller(myWebServiceClientMarshaller());
client.setUnmarshaller(myWebServiceClientMarshaller());
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(keyStore.getInputStream(), keyStorePass.toCharArray());
logger.info("Loaded keyStore: "+keyStore.getURI().toString());
try { keyStore.getInputStream().close(); } catch(IOException e) {}
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(ks, keyStorePass.toCharArray());
KeyStore ts = KeyStore.getInstance("JKS");
ts.load(trustStore.getInputStream(), trustStorePass.toCharArray());
logger.info("Loaded trustStore: "+trustStore.getURI().toString());
try { trustStore.getInputStream().close(); } catch(IOException e) {}
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(ts);
HttpsUrlConnectionMessageSender msgSender = new HttpsUrlConnectionMessageSender();
msgSender.setKeyManagers(keyManagerFactory.getKeyManagers());
msgSender.setTrustManagers(trustManagerFactory.getTrustManagers());
client.setMessageSender(msgSender);
return client;
}
// client port method implementations ...
public MyOperationResponse processMyOperation(MyOperationRequest request) {
return (MyOperationResponse) getWebServiceTemplate().marshalSendAndReceive(request, new SoapActionCallback("urn:ProcessMyOperation"));
}
}