SWS-708 - PayloadValidatingInterceptor errors not clearing SecurityContextHolder

This commit is contained in:
Arjen Poutsma
2011-05-18 14:23:02 +00:00
parent da9e377e3c
commit 95ac6687b6
16 changed files with 460 additions and 67 deletions

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -96,4 +96,6 @@ public interface EndpointInterceptor {
* blocking of the response handler chain.
*/
boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception;
void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex);
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -221,6 +221,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa
interceptorIndex = i;
if (!interceptor.handleRequest(messageContext, mappedEndpoint.getEndpoint())) {
triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext);
triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, null);
return;
}
}
@@ -231,6 +232,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa
// Apply handleResponse methods of registered interceptors
triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext);
triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, null);
}
catch (NoEndpointFoundException ex) {
// No triggering of interceptors if no endpoint is found
@@ -243,6 +245,7 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa
Object endpoint = mappedEndpoint != null ? mappedEndpoint.getEndpoint() : null;
processEndpointException(messageContext, endpoint, ex);
triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext);
triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, ex);
}
}
@@ -359,6 +362,40 @@ public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAwa
}
}
/**
* Trigger afterCompletion callbacks on the mapped EndpointInterceptors.
* Will just invoke afterCompletion for all interceptors whose handleRequest invocation
* has successfully completed and returned true, in addition to the last interceptor who
* returned <code>false</code>.
*
* @param mappedEndpoint the mapped EndpointInvocationChain
* @param interceptorIndex index of last interceptor that successfully completed
* @param ex Exception thrown on handler execution, or <code>null</code> if none
* @see EndpointInterceptor#afterCompletion
*/
private void triggerAfterCompletion(EndpointInvocationChain mappedEndpoint,
int interceptorIndex,
MessageContext messageContext,
Exception ex) throws Exception {
// Apply afterCompletion methods of registered interceptors.
if (mappedEndpoint != null) {
EndpointInterceptor[] interceptors = mappedEndpoint.getInterceptors();
if (interceptors != null) {
for (int i = interceptorIndex; i >= 0; i--) {
EndpointInterceptor interceptor = interceptors[i];
try {
interceptor.afterCompletion(messageContext, mappedEndpoint.getEndpoint(), ex);
}
catch (Throwable ex2) {
logger.error("EndpointInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
}
/**
* Initialize the <code>EndpointAdapters</code> used by this class. If no adapter beans are explicitly set by using
* the <code>endpointAdapters</code> property, we use the default strategies.

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -111,6 +111,10 @@ public abstract class AbstractLoggingInterceptor extends TransformerObjectSuppor
return true;
}
/** Does nothing by default*/
public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) {
}
/**
* Determine whether the {@link #logger} field is enabled.
* <p/>

View File

@@ -257,6 +257,10 @@ public abstract class AbstractValidatingInterceptor extends TransformerObjectSup
return true;
}
/** Does nothing by default.*/
public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) {
}
/**
* Abstract template method that returns the part of the request message that is to be validated.
*

View File

@@ -85,4 +85,8 @@ public class DelegatingSmartEndpointInterceptor implements SmartEndpointIntercep
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
return getDelegate().handleFault(messageContext, endpoint);
}
public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) {
getDelegate().afterCompletion(messageContext, endpoint, ex);
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -16,10 +16,11 @@
package org.springframework.ws.server.endpoint.interceptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ws.context.MessageContext;
import org.springframework.ws.server.EndpointInterceptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Element;
/**
@@ -65,4 +66,10 @@ public class EndpointInterceptorAdapter implements EndpointInterceptor {
public boolean handleFault(MessageContext messageContext, Object endpoint) {
return true;
}
/**
* Does nothing by default.
*/
public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) {
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2006 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,11 +26,6 @@ import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
@@ -40,6 +35,11 @@ import org.springframework.ws.server.EndpointInterceptor;
import org.springframework.xml.transform.ResourceSource;
import org.springframework.xml.transform.TransformerObjectSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* Interceptor that transforms the payload of <code>WebServiceMessage</code>s using XSLT stylesheet. Allows for seperate
* stylesheets for request and response. This interceptor is especially useful when supporting with multiple version of
@@ -125,6 +125,10 @@ public class PayloadTransformingInterceptor extends TransformerObjectSupport
return true;
}
/** Does nothing by default.*/
public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) {
}
public void afterPropertiesSet() throws Exception {
if (requestXslt == null && responseXslt == null) {
throw new IllegalArgumentException("Setting either 'requestXslt' or 'responseXslt' is required");

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -178,6 +178,9 @@ class AddressingEndpointInterceptor implements SoapEndpointInterceptor {
return responseMessageId;
}
public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) {
}
public boolean understands(SoapHeaderElement header) {
return version.understands(header);
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -171,8 +171,8 @@ public class MessageDispatcherTest {
EndpointMapping mappingMock = createMock(EndpointMapping.class);
dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
EndpointInterceptor interceptorMock1 = createMock("interceptor1", EndpointInterceptor.class);
EndpointInterceptor interceptorMock2 = createMock("interceptor2", EndpointInterceptor.class);
EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class);
EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class);
expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(true);
expect(interceptorMock2.handleRequest(messageContext, endpoint)).andReturn(true);
@@ -182,6 +182,9 @@ public class MessageDispatcherTest {
expect(interceptorMock2.handleResponse(messageContext, endpoint)).andReturn(true);
expect(interceptorMock1.handleResponse(messageContext, endpoint)).andReturn(true);
interceptorMock2.afterCompletion(messageContext, endpoint, null);
interceptorMock1.afterCompletion(messageContext, endpoint, null);
EndpointInvocationChain chain =
new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
@@ -208,8 +211,8 @@ public class MessageDispatcherTest {
EndpointMapping mappingMock = createMock(EndpointMapping.class);
dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
EndpointInterceptor interceptorMock1 = createMock("interceptor1", EndpointInterceptor.class);
EndpointInterceptor interceptorMock2 = createMock("interceptor2", EndpointInterceptor.class);
EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class);
EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class);
EndpointInvocationChain chain =
new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
@@ -217,6 +220,8 @@ public class MessageDispatcherTest {
expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(true);
expect(interceptorMock2.handleRequest(messageContext, endpoint)).andReturn(true);
interceptorMock2.afterCompletion(messageContext, endpoint, null);
interceptorMock1.afterCompletion(messageContext, endpoint, null);
adapterMock.invoke(messageContext, endpoint);
@@ -235,13 +240,14 @@ public class MessageDispatcherTest {
EndpointMapping mappingMock = createMock(EndpointMapping.class);
dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
EndpointInterceptor interceptorMock1 = createMock("interceptor1", EndpointInterceptor.class);
EndpointInterceptor interceptorMock2 = createMock("interceptor2", EndpointInterceptor.class);
EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class);
EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class);
Object endpoint = new Object();
expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(false);
expect(interceptorMock1.handleResponse(messageContext, endpoint)).andReturn(true);
interceptorMock1.afterCompletion(messageContext, endpoint, null);
EndpointInvocationChain chain =
new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
@@ -267,13 +273,15 @@ public class MessageDispatcherTest {
EndpointMapping mappingMock = createMock(EndpointMapping.class);
dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
EndpointInterceptor interceptorMock1 = createMock("interceptor1", EndpointInterceptor.class);
EndpointInterceptor interceptorMock2 = createMock("interceptor2", EndpointInterceptor.class);
EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class);
EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class);
Object endpoint = new Object();
expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(true);
expect(interceptorMock2.handleRequest(messageContext, endpoint)).andReturn(false);
expect(interceptorMock2.handleResponse(messageContext, endpoint)).andReturn(false);
interceptorMock1.afterCompletion(messageContext, endpoint, null);
interceptorMock2.afterCompletion(messageContext, endpoint, null);
EndpointInvocationChain chain =
new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
@@ -290,7 +298,7 @@ public class MessageDispatcherTest {
verify(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock);
}
@Test
public void testFaultFlow() throws Exception {
EndpointAdapter adapterMock = createMock(EndpointAdapter.class);
@@ -302,11 +310,12 @@ public class MessageDispatcherTest {
EndpointMapping mappingMock = createMock(EndpointMapping.class);
dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
EndpointInterceptor interceptorMock = createMock(EndpointInterceptor.class);
EndpointInterceptor interceptorMock = createStrictMock(EndpointInterceptor.class);
expect(interceptorMock.handleRequest(messageContext, endpoint)).andReturn(true);
adapterMock.invoke(messageContext, endpoint);
expect(interceptorMock.handleFault(messageContext, endpoint)).andReturn(true);
interceptorMock.afterCompletion(messageContext, endpoint, null);
EndpointInvocationChain chain =
new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock});

View File

@@ -352,7 +352,7 @@
<dependency>
<groupId>org.apache.ws.commons.schema</groupId>
<artifactId>XmlSchema</artifactId>
<version>1.4.3</version>
<version>1.4.5</version>
</dependency>
<!-- O/X Mapping dependencies -->
<!-- Castor -->

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -20,9 +20,6 @@ import java.util.Iterator;
import java.util.Locale;
import javax.xml.namespace.QName;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import org.springframework.ws.client.WebServiceClientException;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
@@ -36,6 +33,9 @@ import org.springframework.ws.soap.SoapMessage;
import org.springframework.ws.soap.server.SoapEndpointInterceptor;
import org.springframework.ws.soap.soap11.Soap11Body;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Interceptor base class for interceptors that handle WS-Security. Can be used on the server side, registered in a
* {@link org.springframework.ws.server.endpoint.mapping.AbstractEndpointMapping#setInterceptors(org.springframework.ws.server.EndpointInterceptor[])
@@ -166,17 +166,19 @@ public abstract class AbstractWsSecurityInterceptor implements SoapEndpointInter
if (!result) {
messageContext.clearResponse();
}
cleanUp();
}
return result;
}
/** Returns <code>true</code>, i.e. fault responses are not secured. */
public boolean handleFault(MessageContext messageContext, Object endpoint) throws Exception {
cleanUp();
return true;
}
public void afterCompletion(MessageContext messageContext, Object endpoint, Exception ex) {
cleanUp();
}
public boolean understands(SoapHeaderElement headerElement) {
return WS_SECURITY_NAME.equals(headerElement.getName());
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,12 +18,12 @@ package org.springframework.ws.soap.security.wss4j;
import java.util.Properties;
import org.springframework.security.core.Authentication;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.memory.InMemoryDaoImpl;
import org.springframework.ws.context.DefaultMessageContext;
import org.springframework.ws.context.MessageContext;
@@ -69,6 +69,7 @@ public abstract class Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCa
// test clean up
messageContext.getResponse();
interceptor.handleResponse(messageContext, null);
interceptor.afterCompletion(messageContext, null, null);
assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication());
}
@@ -83,6 +84,7 @@ public abstract class Wss4jMessageInterceptorSpringSecurityCallbackHandlerTestCa
// test clean up
messageContext.getResponse();
interceptor.handleResponse(messageContext, null);
interceptor.afterCompletion(messageContext, null, null);
assertNull("Authentication created", SecurityContextHolder.getContext().getAuthentication());
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -26,10 +26,11 @@ import org.springframework.ws.soap.saaj.SaajSoapMessage;
import org.springframework.ws.soap.saaj.SaajSoapMessageFactory;
import org.springframework.ws.soap.security.WsSecurityValidationException;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class XwsSecurityInterceptorTest {
private MessageFactory messageFactory;
@@ -48,14 +49,14 @@ public class XwsSecurityInterceptorTest {
@Override
protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext)
throws XwsSecuritySecurementException {
Assert.fail("secure not expected");
fail("secure not expected");
}
@Override
protected void validateMessage(SoapMessage message, MessageContext messageContext)
throws WsSecurityValidationException {
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message;
Assert.assertEquals("Invalid message", request, saajSoapMessage.getSaajMessage());
assertEquals("Invalid message", request, saajSoapMessage.getSaajMessage());
saajSoapMessage.setSaajMessage(validatedRequest);
}
@@ -63,13 +64,14 @@ public class XwsSecurityInterceptorTest {
MessageContext context =
new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory));
interceptor.handleRequest(context, null);
Assert.assertEquals("Invalid request", validatedRequest,
((SaajSoapMessage) context.getRequest()).getSaajMessage());
assertEquals("Invalid request", validatedRequest, ((SaajSoapMessage) context.getRequest()).getSaajMessage());
}
@Test
public void testHandleServerResponse() throws Exception {
final SOAPMessage securedResponse = messageFactory.createMessage();
final boolean[] cleanupCalled = new boolean[1];
cleanupCalled[0] = false;
XwsSecurityInterceptor interceptor = new XwsSecurityInterceptor() {
@Override
@@ -82,21 +84,49 @@ public class XwsSecurityInterceptorTest {
@Override
protected void validateMessage(SoapMessage soapMessage, MessageContext messageContext)
throws WsSecurityValidationException {
Assert.fail("validate not expected");
fail("validate not expected");
}
@Override
protected void cleanUp() {
cleanupCalled[0] = true;
}
};
SOAPMessage request = messageFactory.createMessage();
MessageContext context =
new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory));
context.getResponse();
interceptor.handleResponse(context, null);
Assert.assertEquals("Invalid response", securedResponse,
((SaajSoapMessage) context.getResponse()).getSaajMessage());
interceptor.afterCompletion(context, null, null);
assertEquals("Invalid response", securedResponse, ((SaajSoapMessage) context.getResponse()).getSaajMessage());
assertTrue("Cleanup not called", cleanupCalled[0]);
}
@Test
public void testhandleClientRequest() throws Exception {
public void testHandleServerFault() throws Exception {
final boolean[] cleanupCalled = new boolean[1];
cleanupCalled[0] = false;
XwsSecurityInterceptor interceptor = new XwsSecurityInterceptor() {
@Override
protected void cleanUp() {
cleanupCalled[0] = true;
}
};
SOAPMessage request = messageFactory.createMessage();
MessageContext context =
new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory));
context.getResponse();
interceptor.handleFault(context, null);
interceptor.afterCompletion(context, null, null);
assertTrue("Cleanup not called", cleanupCalled[0]);
}
@Test
public void testHandleClientRequest() throws Exception {
final SOAPMessage request = messageFactory.createMessage();
final SOAPMessage securedRequest = messageFactory.createMessage();
XwsSecurityInterceptor interceptor = new XwsSecurityInterceptor() {
@@ -105,22 +135,21 @@ public class XwsSecurityInterceptorTest {
protected void secureMessage(SoapMessage soapMessage, MessageContext messageContext)
throws XwsSecuritySecurementException {
SaajSoapMessage saajSoapMessage = (SaajSoapMessage) soapMessage;
Assert.assertEquals("Invalid message", request, saajSoapMessage.getSaajMessage());
assertEquals("Invalid message", request, saajSoapMessage.getSaajMessage());
saajSoapMessage.setSaajMessage(securedRequest);
}
@Override
protected void validateMessage(SoapMessage message, MessageContext messageContext)
throws WsSecurityValidationException {
Assert.fail("validate not expected");
fail("validate not expected");
}
};
MessageContext context =
new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory));
interceptor.handleRequest(context);
Assert.assertEquals("Invalid request", securedRequest,
((SaajSoapMessage) context.getRequest()).getSaajMessage());
assertEquals("Invalid request", securedRequest, ((SaajSoapMessage) context.getRequest()).getSaajMessage());
}
@Test
@@ -131,7 +160,7 @@ public class XwsSecurityInterceptorTest {
@Override
protected void secureMessage(SoapMessage message, MessageContext messageContext)
throws XwsSecuritySecurementException {
Assert.fail("secure not expected");
fail("secure not expected");
}
@Override
@@ -147,8 +176,7 @@ public class XwsSecurityInterceptorTest {
new DefaultMessageContext(new SaajSoapMessage(request), new SaajSoapMessageFactory(messageFactory));
context.getResponse();
interceptor.handleResponse(context);
Assert.assertEquals("Invalid response", validatedResponse,
((SaajSoapMessage) context.getResponse()).getSaajMessage());
assertEquals("Invalid response", validatedResponse, ((SaajSoapMessage) context.getResponse()).getSaajMessage());
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -17,9 +17,9 @@
package org.springframework.ws.soap.security.xwss.callback;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
@@ -110,7 +110,7 @@ public class SpringDigestPasswordValidationCallbackHandlerTest {
}
@Test
public void testAuthenticateUserDigestDisbaled() throws Exception {
public void testAuthenticateUserDigestDisabled() throws Exception {
User user = new User(username, "Ernie", false, true, true, true, new GrantedAuthority[0]);
expect(userDetailsService.loadUserByUsername(username)).andReturn(user);

View File

@@ -0,0 +1,287 @@
<?xml version='1.0'?>
<?xml-stylesheet href="../2008/09/xsd.xsl" type="text/xsl"?>
<xs:schema targetNamespace="http://www.w3.org/XML/1998/namespace"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns ="http://www.w3.org/1999/xhtml"
xml:lang="en">
<xs:annotation>
<xs:documentation>
<div>
<h1>About the XML namespace</h1>
<div class="bodytext">
<p>
This schema document describes the XML namespace, in a form
suitable for import by other schema documents.
</p>
<p>
See <a href="http://www.w3.org/XML/1998/namespace.html">
http://www.w3.org/XML/1998/namespace.html</a> and
<a href="http://www.w3.org/TR/REC-xml">
http://www.w3.org/TR/REC-xml</a> for information
about this namespace.
</p>
<p>
Note that local names in this namespace are intended to be
defined only by the World Wide Web Consortium or its subgroups.
The names currently defined in this namespace are listed below.
They should not be used with conflicting semantics by any Working
Group, specification, or document instance.
</p>
<p>
See further below in this document for more information about <a
href="#usage">how to refer to this schema document from your own
XSD schema documents</a> and about <a href="#nsversioning">the
namespace-versioning policy governing this schema document</a>.
</p>
</div>
</div>
</xs:documentation>
</xs:annotation>
<xs:attribute name="lang">
<xs:annotation>
<xs:documentation>
<div>
<h3>lang (as an attribute name)</h3>
<p>
denotes an attribute whose value
is a language code for the natural language of the content of
any element; its value is inherited. This name is reserved
by virtue of its definition in the XML specification.</p>
</div>
<div>
<h4>Notes</h4>
<p>
Attempting to install the relevant ISO 2- and 3-letter
codes as the enumerated possible values is probably never
going to be a realistic possibility.
</p>
<p>
See BCP 47 at <a href="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">
http://www.rfc-editor.org/rfc/bcp/bcp47.txt</a>
and the IANA language subtag registry at
<a href="http://www.iana.org/assignments/language-subtag-registry">
http://www.iana.org/assignments/language-subtag-registry</a>
for further information.
</p>
<p>
The union allows for the 'un-declaration' of xml:lang with
the empty string.
</p>
</div>
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:union memberTypes="xs:language">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value=""/>
</xs:restriction>
</xs:simpleType>
</xs:union>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="space">
<xs:annotation>
<xs:documentation>
<div>
<h3>space (as an attribute name)</h3>
<p>
denotes an attribute whose
value is a keyword indicating what whitespace processing
discipline is intended for the content of the element; its
value is inherited. This name is reserved by virtue of its
definition in the XML specification.</p>
</div>
</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="xs:NCName">
<xs:enumeration value="default"/>
<xs:enumeration value="preserve"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="base" type="xs:anyURI"> <xs:annotation>
<xs:documentation>
<div>
<h3>base (as an attribute name)</h3>
<p>
denotes an attribute whose value
provides a URI to be used as the base for interpreting any
relative URIs in the scope of the element on which it
appears; its value is inherited. This name is reserved
by virtue of its definition in the XML Base specification.</p>
<p>
See <a
href="http://www.w3.org/TR/xmlbase/">http://www.w3.org/TR/xmlbase/</a>
for information about this attribute.
</p>
</div>
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="id" type="xs:ID">
<xs:annotation>
<xs:documentation>
<div>
<h3>id (as an attribute name)</h3>
<p>
denotes an attribute whose value
should be interpreted as if declared to be of type ID.
This name is reserved by virtue of its definition in the
xml:id specification.</p>
<p>
See <a
href="http://www.w3.org/TR/xml-id/">http://www.w3.org/TR/xml-id/</a>
for information about this attribute.
</p>
</div>
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attributeGroup name="specialAttrs">
<xs:attribute ref="xml:base"/>
<xs:attribute ref="xml:lang"/>
<xs:attribute ref="xml:space"/>
<xs:attribute ref="xml:id"/>
</xs:attributeGroup>
<xs:annotation>
<xs:documentation>
<div>
<h3>Father (in any context at all)</h3>
<div class="bodytext">
<p>
denotes Jon Bosak, the chair of
the original XML Working Group. This name is reserved by
the following decision of the W3C XML Plenary and
XML Coordination groups:
</p>
<blockquote>
<p>
In appreciation for his vision, leadership and
dedication the W3C XML Plenary on this 10th day of
February, 2000, reserves for Jon Bosak in perpetuity
the XML name "xml:Father".
</p>
</blockquote>
</div>
</div>
</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>
<div xml:id="usage" id="usage">
<h2><a name="usage">About this schema document</a></h2>
<div class="bodytext">
<p>
This schema defines attributes and an attribute group suitable
for use by schemas wishing to allow <code>xml:base</code>,
<code>xml:lang</code>, <code>xml:space</code> or
<code>xml:id</code> attributes on elements they define.
</p>
<p>
To enable this, such a schema must import this schema for
the XML namespace, e.g. as follows:
</p>
<pre>
&lt;schema . . .>
. . .
&lt;import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2001/xml.xsd"/>
</pre>
<p>
or
</p>
<pre>
&lt;import namespace="http://www.w3.org/XML/1998/namespace"
schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
</pre>
<p>
Subsequently, qualified reference to any of the attributes or the
group defined below will have the desired effect, e.g.
</p>
<pre>
&lt;type . . .>
. . .
&lt;attributeGroup ref="xml:specialAttrs"/>
</pre>
<p>
will define a type which will schema-validate an instance element
with any of those attributes.
</p>
</div>
</div>
</xs:documentation>
</xs:annotation>
<xs:annotation>
<xs:documentation>
<div id="nsversioning" xml:id="nsversioning">
<h2><a name="nsversioning">Versioning policy for this schema document</a></h2>
<div class="bodytext">
<p>
In keeping with the XML Schema WG's standard versioning
policy, this schema document will persist at
<a href="http://www.w3.org/2009/01/xml.xsd">
http://www.w3.org/2009/01/xml.xsd</a>.
</p>
<p>
At the date of issue it can also be found at
<a href="http://www.w3.org/2001/xml.xsd">
http://www.w3.org/2001/xml.xsd</a>.
</p>
<p>
The schema document at that URI may however change in the future,
in order to remain compatible with the latest version of XML
Schema itself, or with the XML namespace itself. In other words,
if the XML Schema or XML namespaces change, the version of this
document at <a href="http://www.w3.org/2001/xml.xsd">
http://www.w3.org/2001/xml.xsd
</a>
will change accordingly; the version at
<a href="http://www.w3.org/2009/01/xml.xsd">
http://www.w3.org/2009/01/xml.xsd
</a>
will not change.
</p>
<p>
Previous dated (and unchanging) versions of this schema
document are at:
</p>
<ul>
<li><a href="http://www.w3.org/2009/01/xml.xsd">
http://www.w3.org/2009/01/xml.xsd</a></li>
<li><a href="http://www.w3.org/2007/08/xml.xsd">
http://www.w3.org/2007/08/xml.xsd</a></li>
<li><a href="http://www.w3.org/2004/10/xml.xsd">
http://www.w3.org/2004/10/xml.xsd</a></li>
<li><a href="http://www.w3.org/2001/03/xml.xsd">
http://www.w3.org/2001/03/xml.xsd</a></li>
</ul>
</div>
</div>
</xs:documentation>
</xs:annotation>
</xs:schema>

View File

@@ -4,7 +4,7 @@
xmlns="http://www.springframework.org/spring-ws/xmlNamespace" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="xml.xsd"/>
<xsd:element name="GetOrderRequest">
<xsd:complexType>