Securing Spring Web Services: Chapter 6

Creating Client Classes

1.   Create a class BookStoreClient in com.bookstore.client package. This client class uses spring’s WebServiceTemplate to access BookStore’s web services. This client also sets the soap action header on the soap message by implementing WebServiceMessageCallback interface. For each type of bookstore’s web service requests (add, get, delete) appropriate soap action is set by the client. This allows correct mapping of endpoint methods with the soap action at the server side.

package com.bookstore.client;

import java.io.IOException;

import javax.xml.transform.TransformerException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.soap.SoapMessage;

import com.bookstore.schema.AddBookRequest;
import com.bookstore.schema.AddBookResponse;
import com.bookstore.schema.Book;
import com.bookstore.schema.DeleteBookRequest;
import com.bookstore.schema.DeleteBookResponse;
import com.bookstore.schema.GetBookRequest;
import com.bookstore.schema.GetBookResponse;
import com.bookstore.schema.ObjectFactory;

@Service
public class BookStoreClient implements WebServiceMessageCallback {
    @Autowired
    private WebServiceTemplate webServiceTemplate;
       private ObjectFactory factory = new ObjectFactory();
       private String action;

    @Override
    public void doWithMessage(final WebServiceMessage message)
            throws IOException, TransformerException {
        if (message instanceof SoapMessage) {
            SoapMessage soapMessage = (SoapMessage) message;
            soapMessage.setSoapAction("http://www.bookstore.com/schema/"+action);
        }
    }

       public String add(Book book) {
           action = "Add";
              AddBookRequest addRequest = factory.createAddBookRequest();
              addRequest.setBook(book);
              AddBookResponse response = (AddBookResponse) webServiceTemplate.marshalSendAndReceive(addRequest, this);
              return response.getMessage();
       }

       public Book get(String name) {
           action = "Get";
              GetBookRequest getRequest = factory.createGetBookRequest();
              getRequest.setName(name);
              GetBookResponse getResponse = (GetBookResponse) webServiceTemplate.marshalSendAndReceive(getRequest, this);
              return getResponse.getBook();
       }

       public String delete(String name) {
           action = "Delete";
              DeleteBookRequest request = factory.createDeleteBookRequest();
              request.setName(name);
              DeleteBookResponse response = (DeleteBookResponse) webServiceTemplate.marshalSendAndReceive(request, this);
              return response.getMessage();
       }
}

2. Configure WebServiceTemplate in applicationContext.xml which will be injected into BookStoreClient. It is in this WebServiceTemplate Wss4jSecurityInterceptor is set.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:oxm="http://www.springframework.org/schema/oxm"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd       
       http://www.springframework.org/schema/oxm
       http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">
      
    <context:annotation-config />
    <context:component-scan base-package="com.bookstore.client" />

       <bean name="webserviceTemplate" class="org.springframework.ws.client.core.WebServiceTemplate">
              <property name="defaultUri" value="http://localhost:8080/bookstore-web-service/services" />
              <property name="marshaller" ref="marshaller" />
              <property name="unmarshaller" ref="unmarshaller" />
              <property name="interceptors">
                     <list>
                           <ref local="wsClientSecurityInterceptor" />
                     </list>
              </property>
       </bean>

       <oxm:jaxb2-marshaller id="marshaller" contextPath="com.bookstore.schema" />
       <oxm:jaxb2-marshaller id="unmarshaller" contextPath="com.bookstore.schema" />

       <bean id="wsClientSecurityInterceptor" class="org.springframework.ws.soap.security.wss4j.Wss4jSecurityInterceptor">
              <!-- configuration to encrypt outgoing request -->
              <property name="securementActions" value="Encrypt" />
              <property name="securementEncryptionUser" value="bookstore-server-import" />
              <property name="securementEncryptionCrypto">
                     <ref bean="keystore" />
              </property>

              <!-- configuration to decrypt incoming response -->
              <property name="validationActions" value="Encrypt" />
              <property name="validationDecryptionCrypto">
                     <ref bean="keystore" />
              </property>
              <property name="validationCallbackHandler">
                     <bean class="org.springframework.ws.soap.security.wss4j.callback.KeyStoreCallbackHandler">
                           <property name="privateKeyPassword" value="client12345" />
                     </bean>
              </property>
       </bean>

       <bean id="keystore" class="org.springframework.ws.soap.security.wss4j.support.CryptoFactoryBean">
              <property name="keyStorePassword" value="client12345" />
              <property name="keyStoreLocation" value="classpath:/bookstore-client-keystore.jks" />
       </bean>
</beans>

3.       In App.java, using BookStoreClient access book store’s web services.

package com.bookstore.client;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.bookstore.schema.Book;

public class App {
    public static void main(String[] args) {
        ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        BookStoreClient bookStoreClient = (BookStoreClient) appContext.getBean("bookStoreClient");

        String responseMessage = null;       
        Book book = createBook();

        responseMessage = bookStoreClient.add(book);
        System.out.println("Add Request: " + responseMessage);

        book = bookStoreClient.get("Spring Web Service");
        System.out.println("Get Request: [Name=" + book.getName() + ", Author=" + book.getAuthor()
                + ", price=" + book.getPrice() + "]");
       
        responseMessage = bookStoreClient.delete("Spring Web Service");
        System.out.println("Delete Request: " + responseMessage);
    }

    private static Book createBook() {
        Book book = new Book();
        book.setName("Spring Web Service");
        book.setAuthor("XYZ");
        book.setPrice("ABC");
        return book;
    }
}

4.    Now we need to add spring ws core and spring ws security dependencies in pom.xml. In next chapter we will learn how to add these dependencies in pom.xml.

No comments :

Post a Comment