SOAP handler is a SOAP message interceptor, which is able to intercept incoming or outgoing SOAP message and manipulate its values. For example, attach a SOAP handler in client side, which will inject authentication credential into the SOAP header block for every outgoing SOAP message that is send by the client. In server side, attach another SOAP handler, to retrieve back the authentication credential in SOAP header block from every incoming SOAP message. In this way we can validate the incoming requests and secure our system.
For this tutorial I will be using the following tools.
- JDK 7
- Eclipse Juno
- Maven2
- GlassFish Metro
- Tomcat 7
In this article, I show you how to create a SOAP handler and attach it to web service, to retrieve the credential in SOAP header block from every incoming SOAP message. And do validation to allow only username as “foo” and password as “bar” to access this published service. If a request comes with an invalid credential, return a response with fault description and fault code. We are going to do the following thing here.
- Create Web Service
- Create SOAP Handler
- Handler Configuration
- Hander Mapping
Create Web Service:
As I have already wrote an article to demonstrate how to create web service, I will not be explaining it again . Please refer JAX-WS Web Integration (Glassfish Metro) to create and deploy a web service in tomcat.
Create Soap Handler:
In order to create a SOAP handler, we have to implement javax.xml.ws.handler.soap.SOAPHandler. We have to give a logical implementation in handleMessage(). This method returns a true in case success and false in case of failure. Be very careful to return false in case of failure or else it will bypass the security and hit to the endpoint. So eventually in all cases web service will be get accessed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | package com.techiekernel.ws.jaxws.handler; import java.io.IOException; import java.util.Iterator; import java.util.Set; import javax.xml.namespace.QName; import javax.xml.soap.Node; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPConstants; import javax.xml.soap.SOAPEnvelope; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFault; import javax.xml.soap.SOAPHeader; import javax.xml.soap.SOAPMessage; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; import javax.xml.ws.soap.SOAPFaultException; public class AuthenticationHandler implements SOAPHandler<SOAPMessageContext> { public boolean handleMessage(SOAPMessageContext context) { System.out.println("handleMessage() called."); Boolean isRequest = (Boolean) context .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); // for request message only, true for outbound messages, false for // inbound if (!isRequest) { try { SOAPMessage soapMsg = context.getMessage(); SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope(); SOAPHeader soapHeader = soapEnv.getHeader(); // if no header, add one if (soapHeader == null) { soapHeader = soapEnv.addHeader(); // No header found, throw exception embedSOAPException(soapMsg, "Missing Header", "ERR:001"); } // Get user Id and password from SOAP header Iterator<Node> it = soapHeader .extractHeaderElements(SOAPConstants.URI_SOAP_ACTOR_NEXT); // if no header block for next actor found? throw exception if (it == null || !it.hasNext()) { embedSOAPException(soapMsg, "No Header Data", "ERR:002"); } String userName = null; String password = null; while (it.hasNext()) { Node node = it.next(); if (node != null && node.getNodeName().equals("userName")) userName = node.getValue(); if (node != null && node.getNodeName().equals("password")) password = node.getValue(); } if (userName == null || password == null) { embedSOAPException(soapMsg, "No userName or password.", "ERR:003"); } // the auth code if (!userName.equals("foo") || !password.equals("bar")) { embedSOAPException(soapMsg, "Authentication Failed", "ERR:004"); } // tracking soapMsg.writeTo(System.out); } catch (SOAPException e) { System.err.println(e); return false; } catch (IOException e) { System.err.println(e); return false; } } // continue other handler chain return true; } public boolean handleFault(SOAPMessageContext context) { System.out.println("handleFault() called."); return true; } public void close(MessageContext context) { System.out.println("close() called"); } public Set<QName> getHeaders() { System.out.println("getHeaders() called"); return null; } private void embedSOAPException(SOAPMessage msg, String reason, String faultCode) throws SOAPException, IOException { SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody(); SOAPFault soapFault = soapBody.getFault(); if (soapFault == null) soapFault = soapBody.addFault(); soapFault.setFaultString(reason); soapFault.setFaultCode(faultCode); msg.writeTo(System.out); } } |
Handler Configuration:
Let’s create define the handler in a handler mapping file and name it as handler.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <javaee:handler-chain> <javaee:handler> <javaee:handler-class>com.techiekernel.ws.jaxws.handler.AuthenticationHandler </javaee:handler-class> </javaee:handler> </javaee:handler-chain> </javaee:handler-chains> |
Handler Mapping:
To attach above SOAP handler to web service FooBarImpl.java, just annotate with @HandlerChain and specify the SOAP handler file name inside. We have to keep the hander configuration file i.e. handler.xml in the class path.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | package com.techiekernel.ws.jaxws.document; import javax.jws.WebMethod; import javax.jws.WebService; import javax.jws.HandlerChain; @WebService @HandlerChain(file="handler.xml") public class FooBarImpl{ public String callFooBar(String name) { // TODO Auto-generated method stub return "FooBar called by " + name; } public Server getServerDetail(String client) { // TODO Auto-generated method stub Server server = new Server(); server.setName("Techie Kernel"); server.setIp("192.168.1.0"); server.setMac("12-75-61-09-12-22"); server.setOs("Ubuntu"); return server; } } |
Now We are ready to deploy the application to the tomcat container.
Source Code:
You can pull the complete code from GitHub. The shared code contains handler code along with the web services.
0 comments:
Post a Comment