SEC-1291: Add logout namespace support for custom success handler. Added attribute "success-handler-ref" to <logout> element in namespace.

This commit is contained in:
Luke Taylor 2009-11-17 17:29:43 +00:00
parent f0a5572188
commit 3444b31615
4 changed files with 47 additions and 20 deletions

View File

@ -25,6 +25,7 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
static final String ATT_LOGOUT_URL = "logout-url"; static final String ATT_LOGOUT_URL = "logout-url";
static final String DEF_LOGOUT_URL = "/j_spring_security_logout"; static final String DEF_LOGOUT_URL = "/j_spring_security_logout";
static final String ATT_LOGOUT_HANDLER = "success-handler-ref";
String rememberMeServices; String rememberMeServices;
@ -33,20 +34,22 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public BeanDefinition parse(Element element, ParserContext parserContext) { public BeanDefinition parse(Element element, ParserContext pc) {
String logoutUrl = null; String logoutUrl = null;
String successHandlerRef = null;
String logoutSuccessUrl = null; String logoutSuccessUrl = null;
String invalidateSession = null; String invalidateSession = null;
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class); BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class);
if (element != null) { if (element != null) {
Object source = parserContext.extractSource(element); Object source = pc.extractSource(element);
builder.getRawBeanDefinition().setSource(source); builder.getRawBeanDefinition().setSource(source);
logoutUrl = element.getAttribute(ATT_LOGOUT_URL); logoutUrl = element.getAttribute(ATT_LOGOUT_URL);
WebConfigUtils.validateHttpRedirect(logoutUrl, parserContext, source); successHandlerRef = element.getAttribute(ATT_LOGOUT_HANDLER);
WebConfigUtils.validateHttpRedirect(logoutUrl, pc, source);
logoutSuccessUrl = element.getAttribute(ATT_LOGOUT_SUCCESS_URL); logoutSuccessUrl = element.getAttribute(ATT_LOGOUT_SUCCESS_URL);
WebConfigUtils.validateHttpRedirect(logoutSuccessUrl, parserContext, source); WebConfigUtils.validateHttpRedirect(logoutSuccessUrl, pc, source);
invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION); invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION);
} }
@ -55,10 +58,19 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
} }
builder.addPropertyValue("filterProcessesUrl", logoutUrl); builder.addPropertyValue("filterProcessesUrl", logoutUrl);
if (!StringUtils.hasText(logoutSuccessUrl)) { if (StringUtils.hasText(successHandlerRef)) {
logoutSuccessUrl = DEF_LOGOUT_SUCCESS_URL; if (StringUtils.hasText(logoutSuccessUrl)) {
pc.getReaderContext().error("Use " + ATT_LOGOUT_URL + " or " + ATT_LOGOUT_HANDLER + ", but not both",
pc.extractSource(element));
}
builder.addConstructorArgReference(successHandlerRef);
} else {
// Use the logout URL if no handler set
if (!StringUtils.hasText(logoutSuccessUrl)) {
logoutSuccessUrl = DEF_LOGOUT_SUCCESS_URL;
}
builder.addConstructorArgValue(logoutSuccessUrl);
} }
builder.addConstructorArgValue(logoutSuccessUrl);
if (!StringUtils.hasText(invalidateSession)) { if (!StringUtils.hasText(invalidateSession)) {
invalidateSession = DEF_INVALIDATE_SESSION; invalidateSession = DEF_INVALIDATE_SESSION;

View File

@ -327,6 +327,10 @@ logout.attlist &=
logout.attlist &= logout.attlist &=
## Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true. ## Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.
attribute invalidate-session {boolean}? attribute invalidate-session {boolean}?
logout.attlist &=
## A reference to a LogoutSuccessHandler implementation which will be used to determine the destination to which the user is taken after logging out.
attribute success-handler-ref {xsd:token}?
request-cache = request-cache =
## Allow the RequestCache used for saving requests during the login process to be set ## Allow the RequestCache used for saving requests during the login process to be set

View File

@ -800,6 +800,11 @@
<xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.</xs:documentation> <xs:documentation>Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.</xs:documentation>
</xs:annotation> </xs:annotation>
</xs:attribute> </xs:attribute>
<xs:attribute name="success-handler-ref" type="xs:token">
<xs:annotation>
<xs:documentation>A reference to a LogoutSuccessHandler implementation which will be used to determine the destination to which the user is taken after logging out.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:attributeGroup> </xs:attributeGroup>
<xs:element name="request-cache"><xs:annotation> <xs:element name="request-cache"><xs:annotation>
<xs:documentation>Allow the RequestCache used for saving requests during the login process to be set</xs:documentation> <xs:documentation>Allow the RequestCache used for saving requests during the login process to be set</xs:documentation>

View File

@ -1,19 +1,9 @@
package org.springframework.security.config.http; package org.springframework.security.config.http;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.not; import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML; import static org.springframework.security.config.ConfigTestUtils.AUTH_PROVIDER_XML;
import static org.springframework.security.config.http.AuthenticationConfigBuilder.AUTHENTICATION_PROCESSING_FILTER_CLASS; import static org.springframework.security.config.http.AuthenticationConfigBuilder.*;
import static org.springframework.security.config.http.AuthenticationConfigBuilder.OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS;
import static org.springframework.security.config.http.AuthenticationConfigBuilder.OPEN_ID_AUTHENTICATION_PROVIDER_CLASS;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
@ -70,6 +60,7 @@ import org.springframework.security.web.authentication.SimpleUrlAuthenticationFa
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.security.web.authentication.logout.LogoutHandler; import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor; import org.springframework.security.web.authentication.preauth.x509.SubjectDnX509PrincipalExtractor;
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter; import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl; import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl;
@ -300,6 +291,21 @@ public class HttpSecurityBeanDefinitionParserTests {
"</http>" + AUTH_PROVIDER_XML); "</http>" + AUTH_PROVIDER_XML);
} }
@Test
public void logoutSuccessHandlerIsSetCorrectly() throws Exception {
setContext(
"<http>" +
" <logout success-handler-ref='logoutHandler' />" +
" <form-login />" +
"</http>" +
"<b:bean id='logoutHandler' class='org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler' />"
+ AUTH_PROVIDER_XML);
LogoutFilter filter = (LogoutFilter) getFilter(LogoutFilter.class);
LogoutSuccessHandler handler = (LogoutSuccessHandler) FieldUtils.getFieldValue(filter, "logoutSuccessHandler");
assertSame(appContext.getBean("logoutHandler"), handler);
}
@Test @Test
public void lowerCaseComparisonIsRespectedBySecurityFilterInvocationDefinitionSource() throws Exception { public void lowerCaseComparisonIsRespectedBySecurityFilterInvocationDefinitionSource() throws Exception {
setContext( setContext(