Java tutorial
/** * Product : Hiperium Project * Architect: Andres Solorzano. * Created : 08-05-2009 - 23:30:00 * * The contents of this file are copyrighted by Andres Solorzano * and it is protected by the license: "GPL V3." You can find a copy of this * license at: http://www.hiperium.com/about/licence.html * * Copyright 2014 Andres Solorzano. All rights reserved. * */ package com.hiperium.integration.access.control; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; import javax.inject.Inject; import javax.validation.constraints.NotNull; import javax.xml.namespace.QName; import javax.xml.soap.SOAPBody; import javax.xml.soap.SOAPException; import javax.xml.soap.SOAPFault; 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; import org.apache.commons.lang.StringUtils; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.hiperium.bo.delegate.SecurityBusinessDelegate; import com.hiperium.commons.CommonsUtil; import com.hiperium.commons.EnumHiperiumTier; import com.hiperium.commons.HiperiumTier; import com.hiperium.commons.log.HiperiumLogger; import com.hiperium.commons.sign.Signature; /** * @author Andres Solorzano * */ public class SoapSignatureHandler implements SOAPHandler<SOAPMessageContext> { /** The LOGGER property for logger messages. */ private static final HiperiumLogger LOGGER = HiperiumLogger.getLogger(SoapSignatureHandler.class); /** The property securityBusinessDelegate. */ @Inject @HiperiumTier(EnumHiperiumTier.INTEGRATION) private SecurityBusinessDelegate securityBusinessDelegate; /* (non-Javadoc) * @see javax.xml.ws.handler.Handler#handleMessage(javax.xml.ws.handler.MessageContext) */ @SuppressWarnings("unchecked") @Override public boolean handleMessage(SOAPMessageContext context) { LOGGER.debug("handleMessage - BEGIN"); // Only message arriving from the client. Not processing responses. Boolean outbound = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); if (!outbound) { // Get the sessionId from the entire HTTP Message StringBuffer sessionIdBuffer = new StringBuffer(); Map<String, List<String>> map = (Map<String, List<String>>) context .get(MessageContext.HTTP_REQUEST_HEADERS); for (String session : this.getHTTPHeader(map, CommonsUtil.SESSIONID)) { sessionIdBuffer.append(session); } // Try to get SOAP header values from the SOAP message try { SOAPMessage msg = context.getMessage(); if (LOGGER.isDebugEnabled()) { System.out.println("REQUEST:"); msg.writeTo(System.out); System.out.println(); } Node node = msg.getSOAPHeader().getFirstChild(); // Header values NodeList nodeList = node.getChildNodes(); // Name, TimeStamp, Signature. if (nodeList.getLength() < 3) { this.generateFault(msg, "Too few header nodes!"); } // Extract the required attributes. Long homeId = Long.valueOf(nodeList.item(0).getFirstChild().getNodeValue()); String signature = nodeList.item(1).getFirstChild().getNodeValue(); String timestamp = nodeList.item(2).getFirstChild().getNodeValue(); if (StringUtils.isBlank(timestamp) || StringUtils.isBlank(signature)) { this.generateFault(msg, "Missing header key/value pairs!"); } // Validates that the user Token exists in the DB for valid registered external Application. String token = this.securityBusinessDelegate.getHomeGatewayBO().findTokenInSession(homeId, sessionIdBuffer.toString()); if (StringUtils.isBlank(token)) { this.generateFault(msg, homeId.toString().concat(" not registered!")); } // Generate comparison signature and compare against what's sent. byte[] secretBytes = Signature.getBytes(token); String localSignature = Signature.createSignature(homeId, timestamp, secretBytes); if (!this.verify(signature, localSignature)) { this.generateFault(msg, "HMAC signatures do not match."); } } catch (Exception e) { throw new RuntimeException("SOAPException thrown.", e); } } LOGGER.debug("handleMessage - END"); return true; //continue other handler chain } /* (non-Javadoc) * @see javax.xml.ws.handler.Handler#close(javax.xml.ws.handler.MessageContext) */ @Override public void close(MessageContext arg0) { // Nothing to do. } /* (non-Javadoc) * @see javax.xml.ws.handler.Handler#handleFault(javax.xml.ws.handler.MessageContext) */ @Override public boolean handleFault(SOAPMessageContext arg0) { return false; } /* (non-Javadoc) * @see javax.xml.ws.handler.soap.SOAPHandler#getHeaders() */ @Override public Set<QName> getHeaders() { return null; } /** * * @param headers * @param header * @return */ private List<String> getHTTPHeader(@NotNull Map<String, List<String>> headers, @NotNull String header) { for (Map.Entry<String, List<String>> entry : headers.entrySet()) { String name = entry.getKey(); if (name.equalsIgnoreCase(header)) return entry.getValue(); } return null; } /** * * @param msg * @param reason */ private void generateFault(SOAPMessage msg, String reason) { try { SOAPBody body = msg.getSOAPBody(); SOAPFault fault = body.addFault(); fault.setFaultString(reason); throw new SOAPFaultException(fault); } catch (SOAPException e) { LOGGER.error(e.getMessage(), e); } } /** * * @param sig1 * @param sig2 * @return */ private boolean verify(String sig1, String sig2) { return Arrays.equals(sig1.getBytes(), sig2.getBytes()); } }