Sunday, January 5, 2014

JAVA Code To Consume the HTTPS SOAP Service - Certificate Based Client Authentication



JAVA Code To Consume the HTTPS SOAP Service - Certificate Based Client Authentication 



Step 1 : Create the keys for the client  and generate the certificate . This way you will have your identity .This way you will present your certificate to server and server will authenticate based on client certificate.  You must supply your certificate as server will have your certificate in its trust.
Step 2: Store the server certificate in trust keystore.  This way you will trust the server.

Step 3: Set the below arguments in client JVM 
-Djavax.net.debug=ssl
-Djavax.net.ssl.keyStoreType=JKS
-Djavax.net.ssl.keyStore=C:/identity/identity/laptopIdentity.jks
-Djavax.net.ssl.keyStorePassword=xxxxx
-Djavax.net.ssl.trustStoreType=jks
-Djavax.net.ssl.trustStore=C:/identity/identitytruststore.jks


Step 4 : customize the below java code as per your WSDL.

WSDL URL : //https://myhost/ServiceProxy?wsdl


package com.test;

import java.net.URL;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.xml.soap.*;
import javax.xml.transform.*;
import javax.xml.transform.stream.*;

public class SOAPJavaClient {

/**
* Starting function to test the soap service
*/
public static void main(String args[]) {
              // Service URL ,Remove "?wsdl" from the WSDL URL.
String https_url = "https://myhost/ServiceProxy";

URL url;

try {
// Create SOAP Connection
SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory
.newInstance();
SOAPConnection soapConnection = soapConnectionFactory
.createConnection();

// Send SOAP Message to SOAP Server

url = new URL(https_url);
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
                      //Use below (2 lines) if Host name verification needs to turned off
MyHostnameVerifier HostVerifier = new MyHostnameVerifier();
con.setHostnameVerifier(HostVerifier);
con.connect();

SOAPMessage response = soapConnection.call(createRequest(),url);


// Print the  SOAP Response
printResponse (response );

soapConnection.close();
} catch (Exception e) {
System.err
.println("Error occurred while sending SOAP Request to Server");
e.printStackTrace();
}
}

private static SOAPMessage createRequest() throws Exception {
// SOAP 1.1 Services
MessageFactory messageFactory = MessageFactory.newInstance();
// For SOAP 1.2 services
// MessageFactory messageFactory =
// MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);

SOAPMessage soapMessage = messageFactory.createMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();

// String serverURI = "myhost";

// SOAP Envelope
SOAPEnvelope envelope = soapPart.getEnvelope();

envelope.addNamespaceDeclaration("ns1",
"https://myhost/ServiceProxy");

SOAPBody soapBody = envelope.getBody();
SOAPElement soapBodyElem = soapBody.addChildElement(
"OperationRequest", "ns1");

SOAPElement soapBodyElem1 = soapBodyElem
.addChildElement("ID");

soapBodyElem1.addTextNode("1");

MimeHeaders headers = soapMessage.getMimeHeaders();
headers.addHeader("SOAPAction",
"http://myhost/Operation");

soapMessage.saveChanges();

/* Print the request message */
System.out.print("Request SOAP Message = ");
soapMessage.writeTo(System.out);
System.out.println();
return soapMessage;
}

/**
* Method used to print the SOAP Response
*/
private static void printResponse(SOAPMessage soapResponse)
throws Exception {
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
Source sourceContent = soapResponse.getSOAPPart().getContent();
System.out.print("\nResponse SOAP Message = ");
StreamResult result = new StreamResult(System.out);
transformer.transform(sourceContent, result);
}

}
//  This code is used when the server certificate 's CN is different than host name or IP.
class MyHostnameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
if (hostname.equals("hostame or IP of the from WSDL"))
return true;
else
return false;
}
}


Let me know if you have any issue . 

10 comments:

  1. Hi ..Could you pls let us know how to generate laptopIdentity.jks and other trust keys and the configuration changes that we need to make in weblogic console to invoke over ssl.

    Regards,
    Kumar

    ReplyDelete
  2. laptopIdentity.jks is the identity key store of the client who is consuming the HTTPS service. Identity store can be created by using the java keytool.
    Please refer the "http://hcgupta.blogspot.com/2013/04/testing-web-service-secured-by-client.html" to generate the identity keystore.

    Sorry I did not get your question,Do you want to set-up the SSL on WebLogic so that published service can be consumed over SSL?

    ReplyDelete
  3. Im trying to call a web service over https , the administrator send me the WSDL file and certificates for my server :

    myserver.der
    myserver.p7b
    myserver.pem
    myserver-bundle.pem

    I installed the certificate myserver.der :

    keytool -import -trustcacerts -alias myserver -file myserver.der


    Questions :

    1) I don't know what to do with the other files (.p7b ; .pem) ?

    2) It seems that the handshake works , but im getting this error :

    com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 407: Proxy Authentication Required

    ReplyDelete
  4. Could you pls kindly show us how to generate key-store?

    ReplyDelete
  5. Hi, how to implement if using .ks file and the .ks file is dynamically change base on some parameters or logic?

    ReplyDelete
  6. Thanks, your code save my life

    ReplyDelete
  7. You would also modify the SOAP message construction part (createSOAPRequest) to match the structure expected How Parse File by the specific SOAP service you are working with.

    ReplyDelete
  8. You would also modify the SOAP message construction part to match the structure expected by The Perantu Panthan the specific SOAP service you are working with.

    ReplyDelete