Hi
I am working on WS-Security and new in WS . I want to use WSS4j (web service security for
java) API to implement WS-Security. Following is a code which performs the required task. But the problem is that here
soap message (mentioned in bold text) is taken as a
string. I have to take the soap message generated by my web service. How can i get this soap message generated by my service. Please help me.
package abc;
/**
*
* @author user
*/
import org.apache.ws.security.components.crypto.Merlin;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xml.security.c14n.Canonicalizer;
import org.w3c.dom.Document;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPMessage;
import javax.xml.transform.dom.DOMSource;
import java.io.ByteArrayInputStream;
//import org.apache.ws.security.crypto.BouncyCastle;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.SOAPPart;
import org.apache.axis.client.AxisClient;
import org.apache.axis.configuration.NullProvider;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.utils.XMLUtils;
//import org.apache.ws.axis.security.util.AxisUtil;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.ws.axis.security.WSDoAllReceiver;
import org.apache.ws.axis.security.WSDoAllSender;
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.apache.ws.security.message.WSEncryptBody;
import org.apache.ws.security.message.WSSAddUsernameToken;
import org.apache.ws.security.message.token.SecurityTokenReference;
import org.apache.ws.security.message.token.Reference;
import org.apache.ws.security.WSSecurityEngine;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.PrintWriter;
/**
* Enter description here.
*
* @author <a href="mailto:jeff@jeffhanson.com">Jeff Hanson</a>
* @version $Revision: 1.1 $
* <p/>
* <p><b>Revisions:</b>
* <p/>
* <p><b>Jul 26, 2005 jhanson:</b>
* <ul>
* <li> Created file.
* </ul>
*/
public class WSSecuritySample
{
[b] private static final String soapMsg =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
"<SOAP-ENV:Envelope" +
" xmlns:SOAP-ENV=\"http://www.w3.org/2003/05/soap-envelope\"\n" +
" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" +
" <SOAP-ENV:Body>" +
" <sayHello xmlns=\"http://jeffhanson.com/services/helloworld\">" +
" <value xmlns=\"\">Hello world!</value>" +
" </sayHello>" +
" </SOAP-ENV:Body>" +
"</SOAP-ENV:Envelope>";[/b] // The following initializes the security engine to the
// default WS-Security settings
private static final WSSecurityEngine secEngine = new WSSecurityEngine();
// The following creates a crypto provider according to the
// class name specified by the system property:
// org.apache.ws.security.crypto.provider
//
// If the provider property is not set, the default class,
// org.apache.ws.security.components.crypto.BouncyCastle, is
// used.
//
// The provider is initialized to the values specified in
// the crypto.properties file. The crypto.properties file
// found in the wss4j jar file specifies
// org.apache.ws.security.components.crypto.Merlin
// as the provider class.
private static final Crypto crypto = CryptoFactory.getInstance();
//private static final CryptoFactory crypto1 = (CryptoFactory) CryptoFactory.getInstance();
private AxisClient engine = null;
private MessageContext msgContext = null;
/**
* Main method
*/
public static void main(String[] args)
{
try
{
WSSecuritySample app = new WSSecuritySample();
Message axisMessage = app.getAxisMessage(soapMsg);
SOAPEnvelope unsignedEnvelope = axisMessage.getSOAPEnvelope();
System.out.println("<<<<<< Unsigned and Unencrypted >>>>>>");
XMLUtils.PrettyElementToWriter(unsignedEnvelope.getAsDOM(), new PrintWriter(System.out));
//
Message samlMsg = app.addUserTokens(unsignedEnvelope);
System.out.println("\n<<<<<< User Tokens >>>>>>");
XMLUtils.PrettyElementToWriter(samlMsg.getSOAPEnvelope().getAsDOM(),new PrintWriter(System.out));
Message encryptedMsg = app.encryptSOAPEnvelope(unsignedEnvelope,
axisMessage);
System.out.println("\n<<<<<< Encrypted >>>>>>");
XMLUtils.PrettyElementToWriter(encryptedMsg.getSOAPEnvelope().getAsDOM(),
new PrintWriter(System.out));
//
Message signedMsg = app.signSOAPEnvelope(unsignedEnvelope);
System.out.println("\n<<<<<< Signed >>>>>>");
XMLUtils.PrettyElementToWriter(signedMsg.getSOAPEnvelope().getAsDOM(), new PrintWriter(System.out));
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* WSSecuritySample constructor
*/
public WSSecuritySample()
{
engine = new AxisClient(new NullProvider());
msgContext = new MessageContext(engine);
}
/**
* Creates and returns an Axis message from a
* SOAP envelope string.
*
* @param unsignedEnvelope a string containing a SOAP
* envelope
* @return <code>Message</code> the Axis message
*/
private Message getAxisMessage(String unsignedEnvelope)
{
InputStream inStream = new ByteArrayInputStream(unsignedEnvelope.getBytes());
Message axisMessage = new Message(inStream);
axisMessage.setMessageContext(msgContext);
return axisMessage;
}
//
public static class SOAPUtil {
/**
* Convert a DOM Document into a soap message.
* <p/>
*
* @param
doc
* @return
* @throws Exception
*/
public static SOAPMessage toSOAPMessage(Document doc) throws Exception {
Canonicalizer c14n =Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS);
byte[] canonicalMessage = c14n.canonicalizeSubtree(doc);
ByteArrayInputStream in = new ByteArrayInputStream(canonicalMessage);
MessageFactory factory = MessageFactory.newInstance();
return factory.createMessage(null, in);
}
}
//
/**
* Creates a signed SOAP message in compliance with WS-Security.
*
* @return <code>Message</code> the signed SOAP envelope
* as an Axis message
* @throws Exception on error
*/
public static Message signSOAPEnvelope(SOAPEnvelope unsignedEnvelope)
throws Exception
{
// WSSignEnvelope signs a SOAP envelope according to the
// WS Specification (X509 profile) and adds the signature data
// to the envelope.
WSSignEnvelope signer = new WSSignEnvelope();
String alias = "16c73ab6-b892-458f-abf5-2f875f74882e";
String password = "security";
signer.setUserInfo(alias, password);
Document doc = unsignedEnvelope.getAsDocument();
// The "build" method, creates the signed SOAP envelope.
// It takes a SOAP Envelope as a W3C Document and adds
// a WSS Signature header to it. The signed elements
// depend on the signature parts that are specified by
// the WSBaseMessage.setParts(java.util.Vector parts)
// method. By default, SOAP Body is signed.
// The "crypto" parameter is the object that implements
// access to the keystore and handling of certificates.
// A default implementation is included:
// org.apache.ws.security.components.crypto.Merlin
Document signedDoc = signer.build(doc, crypto);
// Convert the signed document into a SOAP message.
//Message signedSOAPMsg =(org.apache.axis.Message)AxisUtil.toSOAPMessage(signedDoc);
// Message signedMsg = (Message) SOAPUtil.toSOAPMessage(signedDoc);
Message signedSOAPMsg =(Message)SOAPUtil.toSOAPMessage(signedDoc);
return signedSOAPMsg;
}
/**
* Adds user tokens to a SOAP envelope in compliance with WS-Security.
*
* @return <code>Message</code> the signed SOAP envelope
* as an Axis message
* @throws Exception on error
*/
public Message addUserTokens(SOAPEnvelope unsignedEnvelope)
throws Exception
{
WSEncryptBody wsEncrypt = new WSEncryptBody();
// Get the message as document
Document doc = unsignedEnvelope.getAsDocument();
String username = "joedoe";
String password = "this is a lot of foobar ";
byte[] key = password.getBytes();
// Add the UserNameToken.
WSSAddUsernameToken builder =
new WSSAddUsernameToken("", false);
builder.setPasswordType(WSConstants.PASSWORD_TEXT);
builder.build(doc, username, password);
// Add an Id to it.
Element usrEle =
(Element)(doc.getElementsByTagNameNS(WSConstants.WSSE_NS, "UsernameToken").item(0));
String idValue = "7654";
usrEle.setAttribute("Id", idValue);
// Create a Reference to the UserNameToken.
Reference ref = new Reference(doc);
//Reference ref = new Reference(WSSConfig.getDefaultWSConfig());
ref.setURI("#" + idValue);
ref.setValueType("UsernameToken");
SecurityTokenReference secRef = new SecurityTokenReference(doc);
secRef.setReference(ref);
// adding the namespace
WSSecurityUtil.setNamespace(secRef.getElement(),
WSConstants.WSSE_NS,
WSConstants.WSSE_PREFIX);
// Setting necessary parameters in WSEncryptBody.
wsEncrypt.setKeyIdentifierType(WSConstants.EMBED_SECURITY_TOKEN_REF);
wsEncrypt.setSecurityTokenReference(secRef);
wsEncrypt.setKey(key);
// Encrypt using the using the key
Document encDoc = wsEncrypt.build(doc, crypto);
// Convert the document into a SOAP message.
Message signedMsg = (Message)SOAPUtil.toSOAPMessage(encDoc);
return signedMsg;
}
/**
* Encrypts a SOAP envelope in compliance with WS-Security.
*
* @return <code>Message</code> the signed SOAP envelope
* as an Axis message
* @throws Exception on error
*/
public Message encryptSOAPEnvelope(SOAPEnvelope unsignedEnvelope,
Message axisMessage)
throws Exception
{
WSEncryptBody encrypt = new WSEncryptBody();
encrypt.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
// Before Encryption
Document doc = unsignedEnvelope.getAsDocument();
Document encryptedDoc = encrypt.build(doc, crypto);
// Convert the document into a SOAP message.
Message encryptedMsg = (Message) SOAPUtil.toSOAPMessage(encryptedDoc);
String soapPart = encryptedMsg.getSOAPPartAsString();
((SOAPPart)axisMessage.getSOAPPart()).setCurrentMessage(soapPart,
SOAPPart.FORM_STRING);
encryptedDoc = axisMessage.getSOAPEnvelope().getAsDocument();
// Convert the document into a SOAP message.
Message encryptedSOAPMsg =
(Message)SOAPUtil.toSOAPMessage(encryptedDoc);
return encryptedSOAPMsg;
}
}