Переглянути джерело

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

Luke Taylor 15 роки тому
батько
коміт
3444b31615

+ 19 - 7
config/src/main/java/org/springframework/security/config/http/LogoutBeanDefinitionParser.java

@@ -25,6 +25,7 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
 
     static final String ATT_LOGOUT_URL = "logout-url";
     static final String DEF_LOGOUT_URL = "/j_spring_security_logout";
+    static final String ATT_LOGOUT_HANDLER = "success-handler-ref";
 
     String rememberMeServices;
 
@@ -33,20 +34,22 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
     }
 
     @SuppressWarnings("unchecked")
-    public BeanDefinition parse(Element element, ParserContext parserContext) {
+    public BeanDefinition parse(Element element, ParserContext pc) {
         String logoutUrl = null;
+        String successHandlerRef = null;
         String logoutSuccessUrl = null;
         String invalidateSession = null;
 
         BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(LogoutFilter.class);
 
         if (element != null) {
-            Object source = parserContext.extractSource(element);
+            Object source = pc.extractSource(element);
             builder.getRawBeanDefinition().setSource(source);
             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);
-            WebConfigUtils.validateHttpRedirect(logoutSuccessUrl, parserContext, source);
+            WebConfigUtils.validateHttpRedirect(logoutSuccessUrl, pc, source);
             invalidateSession = element.getAttribute(ATT_INVALIDATE_SESSION);
         }
 
@@ -55,10 +58,19 @@ class LogoutBeanDefinitionParser implements BeanDefinitionParser {
         }
         builder.addPropertyValue("filterProcessesUrl", logoutUrl);
 
-        if (!StringUtils.hasText(logoutSuccessUrl)) {
-            logoutSuccessUrl = DEF_LOGOUT_SUCCESS_URL;
+        if (StringUtils.hasText(successHandlerRef)) {
+            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)) {
             invalidateSession = DEF_INVALIDATE_SESSION;

+ 4 - 0
config/src/main/resources/org/springframework/security/config/spring-security-3.0.rnc

@@ -327,6 +327,10 @@ logout.attlist &=
 logout.attlist &=
 	## Specifies whether a logout also causes HttpSession invalidation, which is generally desirable. If unspecified, defaults to true.
     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 =
     ## Allow the RequestCache used for saving requests during the login process to be set

+ 5 - 0
config/src/main/resources/org/springframework/security/config/spring-security-3.0.xsd

@@ -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:annotation>
     </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:element name="request-cache"><xs:annotation>
       <xs:documentation>Allow the RequestCache used for saving requests during the login process to be set</xs:documentation>

+ 19 - 13
config/src/test/java/org/springframework/security/config/http/HttpSecurityBeanDefinitionParserTests.java

@@ -1,19 +1,9 @@
 package org.springframework.security.config.http;
 
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.not;
-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.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
 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.OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS;
-import static org.springframework.security.config.http.AuthenticationConfigBuilder.OPEN_ID_AUTHENTICATION_PROVIDER_CLASS;
+import static org.springframework.security.config.http.AuthenticationConfigBuilder.*;
 
 import java.lang.reflect.Method;
 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.logout.LogoutFilter;
 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.X509AuthenticationFilter;
 import org.springframework.security.web.authentication.rememberme.InMemoryTokenRepositoryImpl;
@@ -300,6 +291,21 @@ public class HttpSecurityBeanDefinitionParserTests {
                 "</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
     public void lowerCaseComparisonIsRespectedBySecurityFilterInvocationDefinitionSource() throws Exception {
         setContext(