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 bb5d4ac1..a6b6a917 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 @@ -24,9 +24,11 @@ import org.apache.commons.logging.LogFactory; import org.springframework.util.Assert; import org.springframework.ws.context.MessageContext; import org.springframework.ws.soap.SoapBody; +import org.springframework.ws.soap.SoapFault; import org.springframework.ws.soap.SoapHeaderElement; import org.springframework.ws.soap.SoapMessage; import org.springframework.ws.soap.server.SoapEndpointInterceptor; +import org.springframework.ws.soap.soap11.Soap11Body; /** * Interceptor base class for interceptors that handle WS-Security. @@ -42,19 +44,25 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter private static final QName WS_SECURITY_NAME = new QName("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Security"); - /** Logger available to subclasses. */ + /** + * Logger available to subclasses. + */ protected final Log logger = LogFactory.getLog(getClass()); private boolean secureResponse = true; private boolean validateRequest = true; - /** Indicates whether outgoing responsed are to be secured. Defaults to true. */ + /** + * Indicates whether outgoing responsed are to be secured. Defaults to true. + */ public void setSecureResponse(boolean secureResponse) { this.secureResponse = secureResponse; } - /** Indicates whether incoming request are to be validated. Defaults to true. */ + /** + * Indicates whether incoming request are to be validated. Defaults to true. + */ public void setValidateRequest(boolean validateRequest) { this.validateRequest = validateRequest; } @@ -70,6 +78,9 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter catch (WsSecurityValidationException ex) { return handleValidationException(ex, messageContext); } + catch (WsSecurityFaultException ex) { + return handleFaultException(ex, messageContext); + } } else { return true; @@ -87,13 +98,18 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter catch (WsSecuritySecurementException ex) { return handleSecurementException(ex, messageContext); } + catch (WsSecurityFaultException ex) { + return handleFaultException(ex, messageContext); + } } else { return true; } } - /** Returns true, i.e. faults are not secured. */ + /** + * Returns true, i.e. faults are not secured. + */ public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception { return true; } @@ -134,6 +150,30 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter return false; } + /** + * Handles a fault exception.Default implementation logs the given exception, and creates a SOAP Fault with the + * properties of the given exception, and returns false. + * + * @param ex the validation exception + * @param messageContext the message context + * @return true to continue processing the message, false (the default) otherwise + */ + protected boolean handleFaultException(WsSecurityFaultException ex, MessageContext messageContext) { + if (logger.isWarnEnabled()) { + logger.warn("Could not handle request: " + ex.getMessage()); + } + SoapBody response = ((SoapMessage) messageContext.getResponse()).getSoapBody(); + SoapFault fault; + if (response instanceof Soap11Body) { + fault = ((Soap11Body) response).addFault(ex.getFaultCode(), ex.getFaultString(), Locale.ENGLISH); + } + else { + fault = response.addClientOrSenderFault(ex.getFaultString(), Locale.ENGLISH); + } + fault.setFaultActorOrRole(ex.getFaultActor()); + return false; + } + /** * Abstract template method. Subclasses are required to validate the request contained in the given {@link * SoapMessage}, and replace the original request with the validated version. diff --git a/security/src/main/java/org/springframework/ws/soap/security/WsSecurityFaultException.java b/security/src/main/java/org/springframework/ws/soap/security/WsSecurityFaultException.java new file mode 100644 index 00000000..8faeccdc --- /dev/null +++ b/security/src/main/java/org/springframework/ws/soap/security/WsSecurityFaultException.java @@ -0,0 +1,49 @@ +package org.springframework.ws.soap.security; + +import javax.xml.namespace.QName; + +/** + * Exception indicating that a WS-Security executions should result in a SOAP Fault. + * + * @author Arjen Poutsma + * @since 1.0.1 + */ +public abstract class WsSecurityFaultException extends WsSecurityException { + + private QName faultCode; + + private String faultString; + + private String faultActor; + + /** + * Construct a new WsSecurityFaultException with the given fault code, string, and actor. + */ + public WsSecurityFaultException(QName faultCode, String faultString, String faultActor) { + super(faultString); + this.faultCode = faultCode; + this.faultString = faultString; + this.faultActor = faultActor; + } + + /** + * Returns the fault code for the exception. + */ + public QName getFaultCode() { + return faultCode; + } + + /** + * Returns the fault string for the exception. + */ + public String getFaultString() { + return faultString; + } + + /** + * Returns the fault actor for the exception. + */ + public String getFaultActor() { + return faultActor; + } +} diff --git a/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityFaultException.java b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityFaultException.java new file mode 100644 index 00000000..5556cb1c --- /dev/null +++ b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityFaultException.java @@ -0,0 +1,18 @@ +package org.springframework.ws.soap.security.xwss; + +import javax.xml.namespace.QName; + +import org.springframework.ws.soap.security.WsSecurityFaultException; + +/** + * XWSS-specific version of the {@link WsSecurityFaultException}. + * + * @author Arjen Poutsma + * @since 1.0.1 + */ +public class XwsSecurityFaultException extends WsSecurityFaultException { + + public XwsSecurityFaultException(QName faultCode, String faultString, String faultActor) { + super(faultCode, faultString, faultActor); + } +} diff --git a/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptor.java b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptor.java index 421ae3bb..dcfd27d4 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptor.java +++ b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityInterceptor.java @@ -24,6 +24,7 @@ import com.sun.xml.wss.ProcessingContext; import com.sun.xml.wss.XWSSProcessor; import com.sun.xml.wss.XWSSProcessorFactory; import com.sun.xml.wss.XWSSecurityException; +import com.sun.xml.wss.impl.WssSoapFaultException; import org.springframework.beans.factory.InitializingBean; import org.springframework.core.io.Resource; import org.springframework.util.Assert; @@ -86,7 +87,9 @@ public class XwsSecurityInterceptor extends AbstractWsSecurityInterceptor implem this.callbackHandler = new CallbackHandlerChain(callbackHandler); } - /** Sets the policy configuration to use for XWSS. Required. */ + /** + * Sets the policy configuration to use for XWSS. Required. + */ public void setPolicyConfiguration(Resource policyConfiguration) { this.policyConfiguration = policyConfiguration; } @@ -130,6 +133,9 @@ public class XwsSecurityInterceptor extends AbstractWsSecurityInterceptor implem catch (XWSSecurityException ex) { throw new XwsSecuritySecurementException(ex.getMessage(), ex); } + catch (WssSoapFaultException ex) { + throw new XwsSecurityFaultException(ex.getFaultCode(), ex.getFaultString(), ex.getFaultActor()); + } } /** @@ -151,5 +157,9 @@ public class XwsSecurityInterceptor extends AbstractWsSecurityInterceptor implem catch (XWSSecurityException ex) { throw new XwsSecurityValidationException(ex.getMessage(), ex); } + catch (WssSoapFaultException ex) { + throw new XwsSecurityFaultException(ex.getFaultCode(), ex.getFaultString(), ex.getFaultActor()); + } } + } diff --git a/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecuritySecurementException.java b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecuritySecurementException.java index 3813c8e8..44eb3799 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecuritySecurementException.java +++ b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecuritySecurementException.java @@ -18,6 +18,12 @@ package org.springframework.ws.soap.security.xwss; import org.springframework.ws.soap.security.WsSecuritySecurementException; +/** + * XWSS-specific version of the {@link WsSecuritySecurementException}. + * + * @author Arjen Poutsma + * @since 1.0.0 + */ public class XwsSecuritySecurementException extends WsSecuritySecurementException { public XwsSecuritySecurementException(String msg) { diff --git a/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityValidationException.java b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityValidationException.java index 409b5946..7c8af13e 100644 --- a/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityValidationException.java +++ b/security/src/main/java/org/springframework/ws/soap/security/xwss/XwsSecurityValidationException.java @@ -18,6 +18,12 @@ package org.springframework.ws.soap.security.xwss; import org.springframework.ws.soap.security.WsSecurityValidationException; +/** + * XWSS-specific version of the {@link WsSecurityValidationException}. + * + * @author Arjen Poutsma + * @since 1.0.0 + */ public class XwsSecurityValidationException extends WsSecurityValidationException { public XwsSecurityValidationException(String msg) {