DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • How To Validate HTTP Post Request Body - Restful Web Services With Spring Framework | Spring Boot
  • Consuming SOAP Service With Apache CXF and Spring
  • RESTful Web Services With Spring Boot: Reading HTTP POST Request Body
  • Node.js Http Module to Consume Spring RESTful Web Application

Trending

  • How to Introduce a New API Quickly Using Micronaut
  • Useful System Table Queries in Relational Databases
  • Is Big Data Dying?
  • How to Use AWS Aurora Database for a Retail Point of Sale (POS) Transaction System
  1. DZone
  2. Coding
  3. Frameworks
  4. Spring Web Service to Securely Transfer SOAP Request and Response Call

Spring Web Service to Securely Transfer SOAP Request and Response Call

In this post, we explore the way in which you can apply encryption to a SOAP request and response call using a 256-bit key.

By 
Shrisowdhaman Selvaraj user avatar
Shrisowdhaman Selvaraj
·
Nov. 27, 17 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
14.5K Views

Join the DZone community and get the full member experience.

Join For Free

In this article, I will explain the steps to transfer a SOAP Request and Response call securely with a 256-bit key.

I have used the Spring framework with JAXws and AES algorithms for encryption and decryption.

I hope this article will help you to understand this secure way of transferring SOAP calls using a public key as shown in below figure. 

Architecture

Sample Soap UI output

Soap UI Output

Web.xml

<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">

<display-name>Spring Web Service with AES Encryption </display-name>

<servlet>
  <servlet-name>dispatcher</servlet-name> 
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<servlet>
<servlet-name>wsservice</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSSpringServlet</servlet-class> 
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>wsservice</servlet-name> 
  <url-pattern>/AESWS</url-pattern> 
</servlet-mapping>

<listener>
  <listener-class>
  org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>

<session-config>
<session-timeout>5</session-timeout>
</session-config>

</web-app>

Dispatcher-servlet.xml

The Config.properties files are configured in the property-placeholder. The AES Key is configured in these properties files.

Below is the AES encrypted Java file to marshal and unmarshal the data.

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <context:annotation-config />

<context:component-scan base-package="com.shri" />

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix">
  <value>/WEB-INF/views/</value>
  </property>
  <property name="suffix">
    <value>.jsp</value>
  </property>
</bean>

<mvc:resources mapping="/resources/**" location="/resources/" />

<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="message" />
</bean>

<context:property-placeholder location="classpath:config.properties, classpath:message.properties"
ignore-unresolvable="true"/>

<mvc:annotation-driven />

<!-- AWS Encryption starts -->
<bean id="encrypt" class="com.shri.ws.shared.AESEncrypted" >
<constructor-arg value="${aes_key}" type="String"></constructor-arg>  
</bean> 
<!-- AWS Encryption end-->

</beans>

application-context.xml

<?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:ws="http://jax-ws.dev.java.net/spring/core"
xmlns:wss="http://jax-ws.dev.java.net/spring/servlet" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://jax-ws.dev.java.net/spring/core
   http://jax-ws.dev.java.net/spring/core.xsd
   http://jax-ws.dev.java.net/spring/servlet
   http://jax-ws.dev.java.net/spring/servlet.xsd">

<import resource="dispatcher-servlet.xml" />

<!-- Web service binding status -->
<wss:binding url="/AESWS">
  <wss:service>
  <ws:service bean="#shriAESWS" />
  </wss:service>
</wss:binding>
<!-- Web service binding status ends -->

<!-- Web service methods bean Declaration -->

<!-- Service -->
<bean id="shriAESWS" class="com.shri.ws.service.WSAppService">
<property name="enqObjectImpl" ref="enqObjectImpl"></property>
</bean>
<!-- Service Ends -->

<!-- Implementation Object -->
<bean id="enqObjectImpl" class="com.shri.ws.impl.EnqObjectImpl" />
<!-- Implementation Object Ends -->
<!-- Web service methods bean Declaration Ends -->

</beans>

config.properties file

This is the public AES 256-bit key used for Encryption and Decryption.

aes_key= x!A%D*G-KaPdSgVkYp3s6v8y/B?E(H+M

The WSAppService extends SpringBeanAutowiringSupport.

Include your DAO Process once the request contains a valid file.

Create additional request using the autowired @WebMethod (operationName="User_DEFINE") in the method.

@WebService(serviceName = "WSAppService", portName = "WSAppServicePort", 
targetNamespace = "http://example.org/AESWS")
public class WSAppService extends SpringBeanAutowiringSupport {

@Resource
private WebServiceContext wsctx;

static Logger log = Logger.getLogger(WSAppService.class.getName());

private EnqObjectImpl enqObjectImpl;

@WebMethod(exclude = true)
public void setEnqObjectImpl(EnqObjectImpl enqObjectImpl) {
this.enqObjectImpl = enqObjectImpl;
}

//WebService 
@WebMethod(operationName = "WS")
@WebResult(name = "OUTBOUND")
@XmlJavaTypeAdapter(AESEncrypted.class) //Used to encrypt and decrypt
public String startProcess(
@WebParam(name = "INBOUND") @XmlJavaTypeAdapter(AESEncrypted.class) String request ){

    log.info(" Request : " + request);
    String response; // response
    Outbound outbound = new Outbound(); 

    try{
    log.info(request);
    //Validate the request
    if(request.trim().length()>0 && !request.trim().equalsIgnoreCase("?")) 

        //After unmarsel the header request tag, validate the request by XSD schema 
        //Step1
        XmlToObject xmlToObject = new XmlToObject();

        //Step2
        //Convert request string to object 
        Inbound inbound = (Inbound)XmlToObject.convert(Inbound.class, request, outbound);

        if (outbound.getStatus() == "failure") {
          response = outbound.toString(); // Outbound XML tag
          return response;
        }else{
          //Do your DAO process here 
          log.info(inbound.getName());
          log.info(inbound.getAddress());
          //Move to service and start DAO Process
          outbound = enqObjectImpl.startProcess(inbound, outbound);
          outbound.setStatus("success");
        }

    }else{
    outbound.setStatus("failure");
    }

  }catch(Exception err){
    log.info(err.toString());
    outbound.setStatus("failure");
  }
  response = outbound.toString();
  return response;
}

}

XmlToObject 

Convert XML code to an Object by using JAXB; validation is also enabled in this process. If we want, we can push through the response with a valid failure message.

public class XmlToObject {

static Logger log = Logger.getLogger(XmlToObject.class.getName());

public static Object convert (Class entityClass,String xml, Outbound outbound) throws SAXException{

  log.info("Entity class "+ entityClass.getName());
  //XML Validation 
  ValidationEventCollector vec = new ValidationEventCollector();

  Object  inbound = null;
  try {
  //It generate the URL entityClass.getResource() for the folder  
  URL xsdURL = entityClass.getResource("schema.xsd");   

  SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 
  Schema schema = sf.newSchema(xsdURL); 
  JAXBContext jaxbContext = JAXBContext.newInstance(entityClass);

  Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 
  unmarshaller.setSchema(schema);
  unmarshaller.setEventHandler(vec);
  StringReader reader = new StringReader(xml);
  inbound = (Object)unmarshaller.unmarshal(reader);

  } catch (JAXBException err) {
  if (vec != null && vec.hasEvents()) {
          for (ValidationEvent ve : vec.getEvents()) {

              String msg = ve.getMessage();
              ValidationEventLocator vel = ve.getLocator(); 
              int numLigne = vel.getLineNumber();
              int numColonne = vel.getColumnNumber();

              log.info("Error validation xml" + "Error : " + numLigne + "." + numColonne + ": " + msg +" : "+ ve.getSeverity());
              }
          }
    outbound.setStatus("failure");
    if (err.getLinkedException () == null){
           log.debug(err.toString());
          //Add This message to your response by adding additional datatype in Outdata file
    }else{
           log.debug(err.getLinkedException().getMessage());
    }
  }  

  return inbound;
  }
}

AESEncrypted.java

This file helps to encrypt and decrypt the data and it overwrites it with @Service org.springframework.stereotype.Service.

I used base64 code with an Apache common codec jar.

@Service
public class AESEncrypted extends XmlAdapter<String, String>{

    //Secret Key values set from properties files
    private static SecretKeySpec secretKey; 

private static Cipher cipher;

static Logger log = Logger.getLogger(AESEncrypted.class.getName());

public AESEncrypted(){}

//Value set from dispatcher Servlet constructor INJECTION
public AESEncrypted(String awsKey){
  try {
  secretKey = new SecretKeySpec(awsKey.getBytes(), "AES");
    cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
  } catch (Exception e) {
  log.info("Secrate Key Loading issue !! " );
  }
}

/**
 * Encrypts the value to be placed back in XML
 */
@Override
public String marshal(String plaintext)   {
  try{
         cipher.init(Cipher.ENCRYPT_MODE, secretKey);
         byte[] cipherText = cipher.doFinal(plaintext.getBytes("UTF8"));
         String encryptedString = new String(Base64.encodeBase64(cipherText),"UTF-8");
         return encryptedString;
  }catch(Exception err){
  log.info(err.getMessage());
      return "";
   }
}
/**
 * Decrypts the string value
 */
@Override
public String unmarshal(String encryptedText)  {
    try{
      cipher.init(Cipher.DECRYPT_MODE, secretKey);
      byte[] cipherText = Base64.decodeBase64(encryptedText.getBytes("UTF8"));
      String decryptedString = new String(cipher.doFinal(cipherText), "UTF-8");
      return decryptedString;
    }catch(Exception err){
     log.info(err.getMessage());   
      return "";
     }
 }
}

Inbound.java 

Here, we request an XML data file.

I converted the below Java file to an XSD file with the simple steps below. 

1. location> schemagen Program.java

Image title

package com.shri.ws.vo;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.CollapsedStringAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

/**
 * @author shrisowdhaman
 * Nov 15, 2017
 */
@XmlType(name = "REQ",propOrder={"name","address"})
@XmlRootElement(name ="REQ")
public class Inbound {

  private String name;

  private String address;

  @XmlJavaTypeAdapter(CollapsedStringAdapter.class) 
  @XmlElement(name="NAME",required=true, nillable=false)
  public String getName() {
  return name;
  }

  public void setName(String name) {
  this.name = name;
  }

  @XmlJavaTypeAdapter(CollapsedStringAdapter.class) 
  @XmlElement(name="ADDRESS",required=true, nillable=false)
  public String getAddress() {
  return address;
  } 
  public void setAddress(String address) {
  this.address = address;
  }
}

Schema.xsd

Used to validate the request file with a schema. Validation code available in XmlToObject.java 

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="REQ" nillable="true" type="xs:anyType"/>

  <xs:complexType name="REQ">
    <xs:sequence>
      <xs:element name="NAME" type="xs:string"/>
      <xs:element name="ADDRESS" type="xs:string"/>
    </xs:sequence>
  </xs:complexType>


</xs:schema>

EnqObject.java 

public interface EnqObject {

public Outbound startProcess(Inbound inbound,Outbound outbound);
}

EnqObjectImpl.java

@Service
public class EnqObjectImpl implements EnqObject{

static Logger log = Logger.getLogger(EnqObjectImpl.class.getName());

public Outbound startProcess(Inbound inbound, Outbound outbound) {

if (inbound != null) {
    try {
    //Call DAO Area and save the values in database
    log.info("Inside Inbond");
    } catch (Exception err) {
    outbound.setStatus("failure");
    }
  }  else {
  outbound.setStatus("failure");
  }

  return outbound;
  }

}

You can check my Source Code here.

Java, by default, supports 128-bit keys. If you want to use a 256-bit key, follow the below steps.

Update the Java Cryptography Extension (JCE) to Unlimited Strength Jurisdiction Policy Files to support a 256-bit key.

1. Download the java policy files for Java 7 or Java 8.
2. Locate the jre\lib\security directory for the Java instance that the Atom is using.
For example, this location might be:
C:\Program Files\Java\jre1.8.0_144\lib\security. 
C:\Program Files\Java\jdk1.8.0_144\jre\lib\security
3.Replace the following .jar files directory: local_policy.jar and US_export_policy.jar.
4.Stop and restart the eclipse/server.

Check AES Encryption code here.

SOAP Web Protocols Spring Framework Requests Web Service Transfer (computing)

Opinions expressed by DZone contributors are their own.

Related

  • How To Validate HTTP Post Request Body - Restful Web Services With Spring Framework | Spring Boot
  • Consuming SOAP Service With Apache CXF and Spring
  • RESTful Web Services With Spring Boot: Reading HTTP POST Request Body
  • Node.js Http Module to Consume Spring RESTful Web Application

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!