package com.mattfleming; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; import java.text.MessageFormat; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.axis.Message; import org.apache.axis.MessageContext; import org.apache.axis.client.AxisClient; import org.apache.axis.configuration.NullProvider; import org.apache.axis.utils.XMLUtils; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.ws.security.WSConstants; import org.apache.ws.security.WSSConfig; import org.apache.ws.security.components.crypto.Crypto; import org.apache.ws.security.components.crypto.CryptoFactory; import org.apache.ws.security.message.WSSignEnvelope; import org.w3c.dom.Document; /** * Prototype of a proxy class that signs an inbound SOAP message using legacy * (OASIS 2006) security headers. * */ public class WSSecurityWrapperProxy extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet { private static final long serialVersionUID = 1L; private static final Crypto crypto = CryptoFactory.getInstance(); protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/xml"); // set the true destination of the SOAP request PostMethod httppost = new PostMethod("https://therealdestination.com"); try { // setup the outbound message format AxisClient engine = new AxisClient(new NullProvider()); MessageContext msgContext = new MessageContext(engine); WSSConfig config = WSSConfig.getNewInstance(); config.setWsseNS(WSConstants.WSSE_NS_OASIS_2003_06); config.setWsuNS(WSConstants.WSU_NS_OASIS_2003_06); config.setBSTAttributesQualified(false); config.setBSTValuesPrefixed(true); WSSignEnvelope signer = new WSSignEnvelope(config, null, true); // setup the message signer String alias = "key_for_signing"; String password = "key_for_signing_password"; signer.setUserInfo(alias, password); signer.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE); // create an axis message from the posted contents Message axisMessage = new Message(request.getInputStream()); axisMessage.setMessageContext(msgContext); Document signedDoc = signer.build(axisMessage.getSOAPEnvelope() .getAsDocument(), crypto); Writer sw = new StringWriter(); XMLUtils.DocumentToWriter(signedDoc, sw); String signedString = sw.toString(); // send the message to the real end point HttpClient httpclient = new HttpClient(); // need to use corporate proxy httpclient.getHostConfiguration().setProxy( "draconian.proxy.company.com", 8080); RequestEntity ent = new StringRequestEntity(signedString); HttpMethodParams params = new HttpMethodParams(); params.setSoTimeout(20000); httppost.setParams(params); httppost.setRequestEntity(ent); // must be set to be a SOAP request httppost.addRequestHeader("SOAPAction", ""); httpclient.executeMethod(httppost); response.getWriter().print(httppost.getResponseBodyAsString()); } catch (Exception e) { StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); response.getWriter().print( MessageFormat.format(ERROR_SOAP, new Object[] { e.getMessage(), sw.toString() })); } finally { httppost.releaseConnection(); } } private static final String ERROR_SOAP = "soapenv:Client{0}>{1}"; }