Skip to content

Commit 89f054f

Browse files
committed
SWS-345, take two
1 parent c078a4e commit 89f054f

File tree

3 files changed

+49
-24
lines changed

3 files changed

+49
-24
lines changed

core/src/main/java/org/springframework/ws/context/DefaultMessageContext.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ public void readResponse(InputStream inputStream) throws IOException {
8282
response = messageFactory.createWebServiceMessage(inputStream);
8383
}
8484

85+
public WebServiceMessageFactory getMessageFactory() {
86+
return messageFactory;
87+
}
88+
8589
private void checkForResponse() throws IllegalStateException {
8690
if (response != null) {
8791
throw new IllegalStateException("Response message already created");

security/src/main/java/org/springframework/ws/soap/security/wss4j/Wss4jSecurityInterceptor.java

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,16 @@
1616

1717
package org.springframework.ws.soap.security.wss4j;
1818

19+
import java.io.ByteArrayInputStream;
20+
import java.io.ByteArrayOutputStream;
1921
import java.io.IOException;
2022
import java.security.Principal;
2123
import java.security.cert.X509Certificate;
2224
import java.util.Vector;
2325
import javax.security.auth.callback.Callback;
2426
import javax.security.auth.callback.CallbackHandler;
2527
import javax.security.auth.callback.UnsupportedCallbackException;
26-
import javax.xml.soap.SOAPException;
28+
import javax.xml.soap.MessageFactory;
2729

2830
import org.apache.axiom.soap.SOAPEnvelope;
2931
import org.apache.axiom.soap.SOAPFactory;
@@ -44,12 +46,14 @@
4446
import org.springframework.beans.factory.InitializingBean;
4547
import org.springframework.util.Assert;
4648
import org.springframework.util.StringUtils;
49+
import org.springframework.ws.context.DefaultMessageContext;
4750
import org.springframework.ws.context.MessageContext;
4851
import org.springframework.ws.soap.SoapMessage;
4952
import org.springframework.ws.soap.axiom.AxiomSoapMessage;
5053
import org.springframework.ws.soap.axiom.support.AxiomUtils;
5154
import org.springframework.ws.soap.saaj.SaajSoapMessage;
5255
import org.springframework.ws.soap.saaj.SaajSoapMessageException;
56+
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
5357
import org.springframework.ws.soap.security.AbstractWsSecurityInterceptor;
5458
import org.springframework.ws.soap.security.WsSecuritySecurementException;
5559
import org.springframework.ws.soap.security.WsSecurityValidationException;
@@ -440,7 +444,7 @@ protected void secureMessage(SoapMessage soapMessage, MessageContext messageCont
440444
}
441445
RequestData requestData = initializeRequestData(messageContext);
442446

443-
Document envelopeAsDocument = toDocument(soapMessage);
447+
Document envelopeAsDocument = toDocument(soapMessage, messageContext);
444448
try {
445449
// In case on signature confirmation with no other securement
446450
// action, we need to pass an empty securementActionsVector to avoid
@@ -485,7 +489,7 @@ protected void validateMessage(SoapMessage soapMessage, MessageContext messageCo
485489
return;
486490
}
487491

488-
Document envelopeAsDocument = toDocument(soapMessage);
492+
Document envelopeAsDocument = toDocument(soapMessage, messageContext);
489493

490494
// Header processing
491495
WSSecurityEngine securityEngine = WSSecurityEngine.getInstance();
@@ -590,16 +594,27 @@ private void processPrincipal(Vector results) {
590594
}
591595

592596
/** Converts the given {@link SoapMessage} into a {@link Document}. */
593-
private Document toDocument(SoapMessage soapMessage) {
597+
private Document toDocument(SoapMessage soapMessage, MessageContext messageContext) {
594598
if (soapMessage instanceof SaajSoapMessage) {
595-
javax.xml.soap.SOAPMessage saajMessage = ((SaajSoapMessage) soapMessage).getSaajMessage();
599+
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) soapMessage;
600+
// return saajSoapMessage.getSaajMessage().getSOAPPart(); // does not work, see SWS-345
601+
Assert.isInstanceOf(DefaultMessageContext.class, messageContext);
602+
DefaultMessageContext defaultMessageContext = (DefaultMessageContext) messageContext;
603+
Assert.isInstanceOf(SaajSoapMessageFactory.class, defaultMessageContext.getMessageFactory());
604+
MessageFactory messageFactory =
605+
((SaajSoapMessageFactory) defaultMessageContext.getMessageFactory()).getMessageFactory();
596606
try {
597-
saajMessage.saveChanges();
607+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
608+
saajSoapMessage.writeTo(bos);
609+
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
610+
javax.xml.soap.SOAPMessage saajMessage =
611+
messageFactory.createMessage(saajSoapMessage.getSaajMessage().getMimeHeaders(), bis);
612+
saajSoapMessage.setSaajMessage(saajMessage);
613+
return saajMessage.getSOAPPart();
598614
}
599-
catch (SOAPException ex) {
615+
catch (Exception ex) {
600616
throw new SaajSoapMessageException("Could not save changes", ex);
601617
}
602-
return saajMessage.getSOAPPart();
603618
}
604619
else if (soapMessage instanceof AxiomSoapMessage) {
605620
AxiomSoapMessage axiomMessage = (AxiomSoapMessage) soapMessage;
@@ -612,20 +627,10 @@ else if (soapMessage instanceof AxiomSoapMessage) {
612627

613628
/**
614629
* Replaces the contents of the given {@link SoapMessage} with that of the document parameter. Only required when
615-
* using Axiom, since the document returned by {@link #toDocument(org.springframework.ws.soap.SoapMessage)} is live
616-
* for a {@link SaajSoapMessage}.
630+
* using Axiom, since the document returned by {@link #toDocument} is live for a {@link SaajSoapMessage}.
617631
*/
618632
private void replaceMessage(SoapMessage soapMessage, Document envelope) {
619-
if (soapMessage instanceof SaajSoapMessage) {
620-
javax.xml.soap.SOAPMessage saajMessage = ((SaajSoapMessage) soapMessage).getSaajMessage();
621-
try {
622-
saajMessage.saveChanges();
623-
}
624-
catch (SOAPException ex) {
625-
throw new SaajSoapMessageException("Could not save changes", ex);
626-
}
627-
}
628-
else if (soapMessage instanceof AxiomSoapMessage) {
633+
if (soapMessage instanceof AxiomSoapMessage) {
629634
// construct a new Axiom message with the processed envelope
630635
AxiomSoapMessage axiomMessage = (AxiomSoapMessage) soapMessage;
631636
SOAPEnvelope envelopeFromDOMDocument = AxiomUtils.toEnvelope(envelope);

security/src/test/java/org/springframework/ws/soap/security/wss4j/SaajWss4jMessageInterceptorSignTest.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,49 @@
22

33
import java.io.ByteArrayInputStream;
44
import java.io.ByteArrayOutputStream;
5+
import java.util.Iterator;
56
import javax.xml.namespace.QName;
6-
import javax.xml.soap.MessageFactory;
77
import javax.xml.soap.MimeHeaders;
8+
import javax.xml.soap.SOAPHeader;
9+
import javax.xml.soap.SOAPHeaderElement;
810
import javax.xml.soap.SOAPMessage;
11+
import javax.xml.transform.Transformer;
12+
import javax.xml.transform.TransformerFactory;
13+
import javax.xml.transform.dom.DOMResult;
914

1015
import org.springframework.ws.context.DefaultMessageContext;
1116
import org.springframework.ws.context.MessageContext;
1217
import org.springframework.ws.soap.SoapMessage;
1318
import org.springframework.ws.soap.saaj.SaajSoapMessage;
1419
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
20+
import org.springframework.xml.transform.StringSource;
1521

1622
public class SaajWss4jMessageInterceptorSignTest extends Wss4jMessageInterceptorSignTestCase {
1723

24+
private static final String PAYLOAD =
25+
"<tru:StockSymbol xmlns:tru=\"http://fabrikam123.com/payloads\">QQQ</tru:StockSymbol>";
26+
1827
public void testSignAndValidate() throws Exception {
19-
MessageFactory messageFactory = MessageFactory.newInstance();
28+
Transformer transformer = TransformerFactory.newInstance().newTransformer();
2029
interceptor.setSecurementActions("Signature");
2130
interceptor.setEnableSignatureConfirmation(false);
2231
interceptor.setSecurementPassword("123456");
2332
interceptor.setSecurementUsername("rsaKey");
2433
SOAPMessage saajMessage = messageFactory.createMessage();
25-
saajMessage.getSOAPBody()
26-
.addBodyElement(new QName("http://fabrikam123.com/payloads", "StockSymbol", "tru")).addTextNode("QQQ");
34+
transformer.transform(new StringSource(PAYLOAD), new DOMResult(saajMessage.getSOAPBody()));
2735
SoapMessage message = new SaajSoapMessage(saajMessage);
2836
MessageContext messageContext = new DefaultMessageContext(message, new SaajSoapMessageFactory(messageFactory));
2937

3038
interceptor.secureMessage(message, messageContext);
3139

40+
SOAPHeader header = ((SaajSoapMessage) message).getSaajMessage().getSOAPHeader();
41+
Iterator iterator = header.getChildElements(new QName(
42+
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security"));
43+
assertTrue("No security header", iterator.hasNext());
44+
SOAPHeaderElement securityHeader = (SOAPHeaderElement) iterator.next();
45+
iterator = securityHeader.getChildElements(new QName("http://www.w3.org/2000/09/xmldsig#", "Signature"));
46+
assertTrue("No signature header", iterator.hasNext());
47+
3248
ByteArrayOutputStream bos = new ByteArrayOutputStream();
3349
message.writeTo(bos);
3450

0 commit comments

Comments
 (0)