Axis 1.4 Web Service Client Side authentication

So in a previous post, I gave an example of how to setup an Axis 1.4 Web Service client. That is fine if you do not have to login to use the service. Often times however, you do have to authenticate your client especially if your work has paid for the third party Web Service that you want to use. Here you want to use WSS4J. Below are the steps to get yourself setup:

Step 1. Download WSS4J

Step 2. Add the contents of the WSS4J lib directory to your classpath. If you are working with a project in Eclipse, you probably want to copy the contents of WSS4J lib to your own lib directory

Step 3. Create a deployment descriptor file. Below is an example of one that we will refer to as sample.wsdd:

<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
 <transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
  <globalConfiguration >
   <requestFlow >
    <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
     <parameter name="action" value="UsernameToken"/>
     <parameter name="user" value="sampleUsername"/>
     <parameter name="passwordCallbackClass" value="SamplePWCallback"/>
     <parameter name="passwordType" value="PasswordDigest"/>
    </handler>
   </requestFlow >
  </globalConfiguration >
</deployment>

Step 4. Create a CallbackHandler. In my example below, I use the Apache configuration package to get the username and password from a properties file in order to avoid hardcoding it.

import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ws.security.WSPasswordCallback;
public class SamplePWCallback implements CallbackHandler {
   private Configuration _config;
   private static Log _logger = LogFactory.getLog(SamplePWCallback.class);
   public SamplePWCallback () {
      super();
      _logger.info("Initializing Sample PW Callback");
      _config = null;
      try {
         _config = new PropertiesConfiguration("sample.properties");
      }
      catch (ConfigurationException ce) {
         _logger.error("Error loading configuration file", ce);
      }
   }
   public void handle(Callback[] callbacks) throws IOException,
      UnsupportedCallbackException {
      for (int i = 0; i < callbacks.length; i++) {
         if (callbacks[i] instanceof WSPasswordCallback) {
            WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
            // set the password given a username
            if (_config.getString("username").equals(pc.getIdentifier())) {
               pc.setPassword(_config.getString("password"));
            }
         } 
         else {
            throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
         }
      }
   }
}

Step 5. Access your wsdd in your Web Service client. Let’s assume the global weather Web Service that I used in the previous Axis 1.4 blog post required authentication. Here is what your client would look like.

import NET.webserviceX.www.*;
import org.apache.axis.configuration.FileProvider;
public class HelloWeather {
   public static void main(String[] args) throws Exception {
      FileProvider wsdd = new FileProvider("sample.wsdd");
      wsdd.setSearchClasspath(true);
      GlobalWeatherLocator locator = new GlobalWeatherLocator(wsdd);
      GlobalWeatherSoap globalWeatherSoap = locator.getGlobalWeatherSoap();
      System.out.println("Weather for New York");
      System.out.println(globalWeatherSoap.getWeather("New York", "United States"));
   }
}