I'm developing a JAX-WS webservice that must validate incoming SOAP messages according to the XML Digital Signature specification. I have to manipulate incoming massages to match some transformations made to the reference beferore signing and not reported in the XML document. I use JDOM to do this. I'm noticing a strange behaviour, I can validate the very first incoming message but then validation fails on subsequent messages (on both signature and reference). If i restart the Application Server (Websphere) i can validate the first message. Is this issue related to dirty data shared among subsequnt web service invocations?
Here is the SOAP Handler implementation:
@Override
public boolean handleMessage(SOAPMessageContext messageContext) {
// get the message from the context
SOAPMessage message = messageContext.getMessage();
// is an outgoing message?
Boolean isOutgoing = (Boolean) messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if(!isOutgoing){
// incoming message...
// Retrieve the SOAP part of the incoming message
SOAPPart soapPart = message.getSOAPPart();
InputStream inStream = null;
try {
Document doc = null;
// Retrieve the SOAP Envelope of the incoming message
Source source = soapPart.getContent();
inStream = ((StreamSource)source).getInputStream();
// Instantiate a Document containing the SOAP Envelope
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(inStream);
// Use JDOM to retrieve the CommandMessage element and add the xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" namespace declaration
org.jdom2.input.DOMBuilder jdomBuilder = new org.jdom2.input.DOMBuilder();
org.jdom2.Document jdomDocument = jdomBuilder.build(doc);
org.jdom2.Element jdomBodyElement = jdomDocument.getRootElement().getChild("Body", org.jdom2.Namespace.getNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/"));
org.jdom2.Element jdomCommandMessageElement = jdomBodyElement.getChild("CommandMessage", org.jdom2.Namespace.getNamespace("", "http://www.cryptomathic.com/ckms"));
jdomCommandMessageElement.addNamespaceDeclaration(org.jdom2.Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"));
// Instantiate W3C Document to be validated
org.jdom2.Document jdomSignedDocument = new org.jdom2.Document(jdomCommandMessageElement.detach());
org.jdom2.output.DOMOutputter outputter = new org.jdom2.output.DOMOutputter();
Document signedDocument = outputter.output(jdomSignedDocument);
// Find Signature element
NodeList nl = signedDocument.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
// Create a DOMValidateContext and specify a KeyValue KeySelector and document context
DOMValidateContext valContext = new DOMValidateContext(new KeyValueKeySelector(), nl.item(0));
// Create a DOM XMLSignatureFactory that will be used to unmarshal the
// document containing the XMLSignature
XMLSignatureFactory fac = XMLSignatureFactory.getInstance("DOM");
// unmarshal the XMLSignature
XMLSignature signature = fac.unmarshalXMLSignature(valContext);
boolean coreValidity = signature.validate(valContext);
// Check core validation status
if (coreValidity == false) {
System.out.println("Signature failed core validation");
boolean sv = signature.getSignatureValue().validate(valContext);
System.out.println("signature validation status: " + sv);
// check the validation status of each Reference
Iterator i = signature.getSignedInfo().getReferences().iterator();
for (int j=0; i.hasNext(); j++) {
Reference ref = (Reference) i.next();
boolean refValid = ref.validate(valContext);
System.out.println("ref["+j+"] validity status: " + refValid);
}
} else {
System.out.println("Signature passed core validation");
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
inStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return true;
}
And here is the console output for the first request:
Signature passed core validation
But for subsequent requests:
Signature failed core validation
signature validation status: false
ref[0] validity status: false
Regards, Giovanni