Monday, February 11, 2013

Apache CXF: how to consume a Web Service through HTTPS

When the web service has to be consumed through an SSL network connection, it is not enough to change the endpoint prefix of the soap client, but some configuration is needed.

This article tries to explain how to configure your soap client to consume a Web Service with CXF through HTTPS.

Prepare a Java Keystore

With the command line keytool, prepare a Java Keystore keystore.jks file which contains the SSL certificate (in this example named server.cer) of the server that provide the Web Service you want to connect to:

  keytool -importcert -file server.cer -keystore keystore.jks -alias myAlias -storepass keystorePwd
 

The code

In your java code, obtain your SOAP Client:

  MyClassWS myClassWS;
  
  // This is the real https URL
  String endpointAddress = "https://my-ws-endpoint.com";
  
  Service service = Service.create(SERVICE_NAME);
  
  service.addPort(PORT_NAME, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);
  
  myClassWS = service.getPort(MyClassWS.class);
  
  JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
  
  // Add some logging
  factory.getInInterceptors().add(new LoggingInInterceptor());
  factory.getOutInterceptors().add(new LoggingOutInterceptor());
  
  factory.setServiceClass(MyClassWS.class);
  factory.setAddress(endpointAddress);
  myClassWS = (MyClassWS) factory.create();
  Client client = ClientProxy.getClient(myClassWS);
 

Configure the Client HTTPConduit:

  HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
  TLSClientParameters tlsParams = new TLSClientParameters();
  tlsParams.setSecureSocketProtocol("SSL");
  FiltersType filters = new FiltersType();
  filters.getInclude().add("SSL_RSA_WITH_RC4_128_MD5");
  filters.getInclude().add("SSL_RSA_WITH_RC4_128_SHA");
  tlsParams.setCipherSuitesFilter(filters);
  httpConduit.setTlsClientParameters(tlsParams);
 

Now you need to tell your JVM that you actually trust the server that provides the server.cer certificate - contained in the keystore you created - to your client:

  KeyStore keyStore;
  
  try {
  
   keyStore = KeyStore.getInstance("JKS");
   
   String trustpass = "keystorePwd";
   
   keyStore.load(this.getClass().getResourceAsStream("/path/to/your/keystore.jks"), trustpass.toCharArray());
   TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
   trustFactory.init(keyStore);
   TrustManager[] tm = trustFactory.getTrustManagers();
   tlsParams.setTrustManagers(tm);
  
  } catch (KeyStoreException e) {
   e.printStackTrace();
  } catch (NoSuchAlgorithmException e) {
   e.printStackTrace();
  } catch (CertificateException e) {
   e.printStackTrace();
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
  }
 

Now, calling the request methods, the SOAP Client should be able to successfully establish a HTTPS connection with the endpoint server.

2 comments:

  1. pleasant bLog! its fascinating. much obliged to you for sharing.
    Grazie

    ReplyDelete
  2. This was a really great contest and hopefully I can attend the next one. It was alot of fun and I really enjoyed myself..
    embroidery digitizing service

    ReplyDelete