Client Side Configuration

To provide security the web service client can be configured either programmatically or using a deployment descriptor file. The web services java client example (see Client Side Configuration) details how to create a deployment descriptor programmatically by adding UsernameToken token and configuring the client to sign and encrypt the incoming soap request.

The example of deployment descriptor file is shown in Client Side Configuration:

Figure 1. client_config.wsdd
<?xml version="1.0"?>
<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"/>
    </requestFlow>

    <responseFlow>
     <handler type=
"java:org.apache.ws.axis.security.WSDoAllReceiver">
      <parameter name="passwordCallbackClass"
        value="test.ClientPWCallback"/>
      <parameter name="action"
                 value="Signature Encrypt"/>
      <parameter name="signaturePropFile"
                 value="client-crypto.properties" />
     </handler>
    </responseFlow>

  </globalConfiguration>
</deployment>

The deployment descriptor file (Client Side Configuration) contains the request flow and response flow specified for incoming and outgoing SOAP messages.

As on the server side, the request flow will contain action UsernameToken Signature Encrypt.

Note that request flow does not specify any actions or security configuration in the deployment descriptor. In Client Side Configuration below you will see that it can be added programmatically instead of specifying in deployment descriptor file.

The action UsernameToken is not specified in the response flow. This means that the UsernameToken will not be included into SOAP message.

The value of signaturePropFile specifies the name of the signature crypto property file to use. This file contains the properties used for signing and encrypting the SOAP message. A sample crypto property file is shown in Client Side Configuration.

Figure 2. client-crypto.properties
org.apache.ws.security.crypto.provider=
org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=password
org.apache.ws.security.crypto.merlin.file=client.keystore

The value of org.apache.ws.security.crypto.merlin.file in Client Side Configuration specifies the client's keystore file. Keystore File Creation how to create file client.keystore.

The security handler also requires a callback class, test.ClientPWCallback, to be implemented. The example of an implementation for test.ClientPWCallback is shown in Client Side Configuration:

Figure 3. ClientPWCallback.java
package test;

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.ws.security.WSPasswordCallback;


/**
 * Implementation of password callback class.
 */
public class ClientPWCallback implements CallbackHandler {

  /**
   * Retrieve or display the information requested in the
   * provided Callbacks.
   *
   * @param callbacks an array of Callback objects provided
   * by an underlying security service which contains the
   * information requested to be retrieved or displayed.
   *
   * @throws IOException if an input or output error occurs.
   * @throws UnsupportedCallbackException if the implementation
   * of this method does not support one or more of the Callbacks
   * specified in the callbacks parameter.
   */
  public void handle(final Callback[] callbacks
    throws IOException, UnsupportedCallbackException {

    for (int i = 0; i < callbacks.length; i++) {
      if (callbacks[i] instanceof WSPasswordCallback) {
        final WSPasswordCallback pc =
          (WSPasswordCallback) callbacks[i];
        if ("beantester".equals(pc.getIdentifer())) {
          pc.setPassword("password");
        } else if ("curam-sv".equals(pc.getIdentifer())) {
          pc.setPassword("password");
        }
      } else {
        throw new UnsupportedCallbackException(callbacks[i],
          "Unrecognized Callback");
      }
    }
  }
}

The request flow may be configured programmatically before invoking a web service. Client Side Configuration shows how to configure the request flow for the SecureWebService programmatically, and then invoke the web service.

Figure 4. WebServiceTest.java
package test;

import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
import org.apache.ws.security.handler.WSHandlerConstants;
import wsconnector.SecureWebServiceInput;
import wsconnector.SecureWebServiceServiceLocator;
import wsconnector.SecureWebServiceSoapBindingStub;

public class WebServiceTest {

  /**
   * Configures web service's request flow and call
   * secure web service.
   */
  public void callSecureWebservice() {

    final EngineConfiguration config = new FileProvider(
      ClassLoader.getSystemResourceAsStream(
        "client_config.wsdd"));

    final SecureWebServiceServiceLocator locator =
      new SecureWebServiceServiceLocator(config);

    final SecureWebServiceSoapBindingStub call =
      (SecureWebServiceSoapBindingStub)
        locator.getSecureWebService();

    call._setProperty(WSHandlerConstants.ACTION,
      WSHandlerConstants.USERNAME_TOKEN + " "
      + WSHandlerConstants.SIGNATURE + " "
      + WSHandlerConstants.ENCRYPT + " ");
    call._setProperty(WSHandlerConstants.PASSWORD_TYPE,
      "PasswordText");
    call._setProperty(WSHandlerConstants.SIGNATURE_PARTS,
      "{Element}{http://docs.oasis-open.org/"
      + "wss/2004/01/oasis-200401-wss-"
      + "wssecurity-secext-1.0.xsd}UsernameToken; "
      + "{Content}{}Body");
    call._setProperty(WSHandlerConstants.ENCRYPTION_PARTS,
      "{Element}{http://docs.oasis-open.org/"
      + "wss/2004/01/oasis-200401-wss-"
      + "wssecurity-secext-1.0.xsd}UsernameToken; "
      + "{Content}{}Body");
    call._setProperty(WSHandlerConstants.USER,
      "beantester");
    call._setProperty(WSHandlerConstants.PW_CALLBACK_CLASS,
      "test.ClientPWCallback");
    call._setProperty(WSHandlerConstants.SIG_PROP_FILE,
      "client-crypto.properties");
    call._setProperty(WSHandlerConstants.ENC_KEY_ID,
      "X509KeyIdentifier");
    call._setProperty(WSHandlerConstants.ENCRYPTION_USER,
      "curam");

    final SecureWebServiceInput details =
      new SecureWebServiceInput();
    details.setIntValue(47277);

    call.oper(details);

  }
}