From ce72cbba2fa7fa33d54418ed54f92a75ff49e4b7 Mon Sep 17 00:00:00 2001 From: Tareq Abedrabbo Date: Wed, 28 Apr 2010 20:51:13 +0000 Subject: [PATCH] SWS-193 - added skipValidationIfNoHeaderPresent --- .../AbstractWsSecurityInterceptor.java | 38 ++++++++++++++++++- ...Wss4jMessageInterceptorHeaderTestCase.java | 30 ++++++++------- .../security/wss4j/noSecurityHeader-soap.xml | 5 +++ 3 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 security/src/test/resources/org/springframework/ws/soap/security/wss4j/noSecurityHeader-soap.xml diff --git a/security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java b/security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java index 03d326f1..0690d920 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java +++ b/security/src/main/java/org/springframework/ws/soap/security/AbstractWsSecurityInterceptor.java @@ -16,6 +16,7 @@ package org.springframework.ws.soap.security; +import java.util.Iterator; import java.util.Locale; import javax.xml.namespace.QName; @@ -29,6 +30,7 @@ import org.springframework.ws.context.MessageContext; import org.springframework.ws.server.EndpointExceptionResolver; import org.springframework.ws.soap.SoapBody; import org.springframework.ws.soap.SoapFault; +import org.springframework.ws.soap.SoapHeader; import org.springframework.ws.soap.SoapHeaderElement; import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.server.SoapEndpointInterceptor; @@ -61,6 +63,8 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter private boolean secureRequest = true; private boolean validateResponse = true; + + private boolean skipValidationIfNoHeaderPresent = false; private EndpointExceptionResolver exceptionResolver; @@ -89,11 +93,17 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter this.exceptionResolver = exceptionResolver; } + /** Allows skipping validation if no security header is present. */ + public void setSkipValidationIfNoHeaderPresent( + boolean skipValidationIfNoHeaderPresent) { + this.skipValidationIfNoHeaderPresent = skipValidationIfNoHeaderPresent; + } + /* * Server-side */ - /** + /** * Validates a server-side incoming request. Delegates to {@link #validateMessage(org.springframework.ws.soap.SoapMessage,org.springframework.ws.context.MessageContext)} * if the {@link #setValidateRequest(boolean) validateRequest} property is true. * @@ -106,6 +116,9 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter public final boolean handleRequest(MessageContext messageContext, Object endpoint) throws Exception { if (validateRequest) { Assert.isInstanceOf(SoapMessage.class, messageContext.getRequest()); + if(skipValidationIfNoHeaderPresent && !isSecurityHeaderPresent((SoapMessage) messageContext.getRequest())){ + return true; + } try { validateMessage((SoapMessage) messageContext.getRequest(), messageContext); return true; @@ -122,7 +135,7 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter } } - /** + /** * Secures a server-side outgoing response. Delegates to {@link #secureMessage(org.springframework.ws.soap.SoapMessage,org.springframework.ws.context.MessageContext)} * if the {@link #setSecureResponse(boolean) secureResponse} property is true. * @@ -213,6 +226,9 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter if (validateResponse) { Assert.isTrue(messageContext.hasResponse(), "MessageContext contains no response"); Assert.isInstanceOf(SoapMessage.class, messageContext.getResponse()); + if(skipValidationIfNoHeaderPresent && !isSecurityHeaderPresent((SoapMessage) messageContext.getRequest())){ + return true; + } try { validateMessage((SoapMessage) messageContext.getResponse(), messageContext); return true; @@ -320,4 +336,22 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter throws WsSecuritySecurementException; protected abstract void cleanUp(); + + /** + * Iterates over header elements and returns true if WS-Security header is found. + */ + private boolean isSecurityHeaderPresent(SoapMessage message) { + SoapHeader soapHeader = message.getSoapHeader(); + if(soapHeader == null){ + return false; + } + Iterator elements = soapHeader.examineAllHeaderElements(); + while(elements.hasNext()){ + SoapHeaderElement e = elements.next(); + if(e.getName().equals(WS_SECURITY_NAME)){ + return true; + } + } + return false; + } } diff --git a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java index 202d6e8f..0f49de7d 100755 --- a/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java +++ b/security/src/test/java/org/springframework/ws/soap/security/wss4j/Wss4jMessageInterceptorHeaderTestCase.java @@ -16,11 +16,15 @@ package org.springframework.ws.soap.security.wss4j; +import static org.junit.Assert.*; + import java.io.ByteArrayOutputStream; import java.util.Iterator; import java.util.Properties; + import javax.xml.namespace.QName; +import org.junit.Test; import org.springframework.ws.context.DefaultMessageContext; import org.springframework.ws.context.MessageContext; import org.springframework.ws.soap.SoapHeaderElement; @@ -28,11 +32,6 @@ import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.security.WsSecurityValidationException; import org.springframework.ws.soap.security.wss4j.callback.SimplePasswordValidationCallbackHandler; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; - public abstract class Wss4jMessageInterceptorHeaderTestCase extends Wss4jTestCase { private Wss4jSecurityInterceptor interceptor; @@ -50,7 +49,7 @@ public abstract class Wss4jMessageInterceptorHeaderTestCase extends Wss4jTestCas interceptor.setValidationCallbackHandler(callbackHandler); interceptor.afterPropertiesSet(); } - + @Test public void testValidateUsernameTokenPlainText() throws Exception { SoapMessage message = loadSoap11Message("usernameTokenPlainTextWithHeaders-soap.xml"); @@ -76,17 +75,20 @@ public abstract class Wss4jMessageInterceptorHeaderTestCase extends Wss4jTestCas } - @Test + @Test(expected=WsSecurityValidationException.class) public void testEmptySecurityHeader() throws Exception { SoapMessage message = loadSoap11Message("emptySecurityHeader-soap.xml"); MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); - try { - interceptor.validateMessage(message, messageContext); - fail("validation must fail for an empty security header."); - } - catch (WsSecurityValidationException e) { - // expected - } + interceptor.validateMessage(message, messageContext); + } + + @Test + public void testSkipValidationOnEmptyHeader() throws Exception { + SoapMessage message = loadSoap11Message("noSecurityHeader-soap.xml"); + MessageContext messageContext = new DefaultMessageContext(message, getSoap11MessageFactory()); + interceptor.setSkipValidationIfNoHeaderPresent(true); + boolean result = interceptor.handleRequest(messageContext, null); + assertTrue("handeRequest result must be true", result); } @Test diff --git a/security/src/test/resources/org/springframework/ws/soap/security/wss4j/noSecurityHeader-soap.xml b/security/src/test/resources/org/springframework/ws/soap/security/wss4j/noSecurityHeader-soap.xml new file mode 100644 index 00000000..18e3966d --- /dev/null +++ b/security/src/test/resources/org/springframework/ws/soap/security/wss4j/noSecurityHeader-soap.xml @@ -0,0 +1,5 @@ + + + QQQ + +