瀏覽代碼

SEC-745: Added LogoutSuccessHandler strategy for use in LogoutFilter.

Luke Taylor 16 年之前
父節點
當前提交
9cb361e88a

+ 169 - 0
core/src/main/java/org/springframework/security/ui/AbstractAuthenticationTargetUrlRequestHandler.java

@@ -0,0 +1,169 @@
+package org.springframework.security.ui;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.security.Authentication;
+import org.springframework.security.ui.logout.LogoutHandler;
+import org.springframework.security.util.RedirectUtils;
+import org.springframework.security.util.UrlUtils;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+/**
+ * Base class containing the logic used by strategies which handle redirection to a URL and
+ * are passed an <tt>Authentication</tt> object as part of the contract.
+ * See {@link AuthenticationSuccessHandler} and {@link LogoutHandler}, for example.
+ * <p>
+ * Uses the following logic sequence to determine how it should handle the forward/redirect
+ * <ul>
+ * <li>
+ * If the <tt>alwaysUseDefaultTargetUrl</tt> property is set to true, the <tt>defaultTargetUrl</tt> property
+ * will be used for the destination.
+ * </li>
+ * <li>
+ * If a parameter matching the <tt>targetUrlParameter</tt> has been set on the request, the value will be used as
+ * the destination.
+ * </li>
+ * <li>
+ * If the <tt>useReferer</tt> property is set, the "Referer" HTTP header value will be used, if present.
+ * </li>
+ * <li>
+ * As a fallback option, the <tt>defaultTargetUrl</tt> value will be used.
+ * </li>
+ *
+ * @author Luke Taylor
+ * @version $Id$
+ * @since 2.5
+ */
+public abstract class AbstractAuthenticationTargetUrlRequestHandler {
+
+    public static String DEFAULT_TARGET_PARAMETER = "spring-security-redirect";
+    protected final Log logger = LogFactory.getLog(this.getClass());
+    private String targetUrlParameter = DEFAULT_TARGET_PARAMETER;
+    private String defaultTargetUrl = "/";
+    private boolean alwaysUseDefaultTargetUrl = false;
+    private boolean useRelativeContext = false;
+    private boolean useReferer = false;
+
+    protected AbstractAuthenticationTargetUrlRequestHandler() {
+    }
+
+    protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+            throws IOException, ServletException {
+        String targetUrl = determineTargetUrl(request, response);
+
+        RedirectUtils.sendRedirect(request, response, targetUrl, useRelativeContext);
+    }
+
+    private String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
+        if (isAlwaysUseDefaultTargetUrl()) {
+            return defaultTargetUrl;
+        }
+
+        // Check for the parameter and use that if available
+        String targetUrl = request.getParameter(targetUrlParameter);
+
+        if (StringUtils.hasText(targetUrl)) {
+            try {
+                targetUrl = URLDecoder.decode(targetUrl, "UTF-8");
+            } catch (UnsupportedEncodingException e) {
+                throw new IllegalStateException("UTF-8 not supported. Shouldn't be possible");
+            }
+
+            logger.debug("Found targetUrlParameter in request: " + targetUrl);
+
+            return targetUrl;
+        }
+
+        if (useReferer && !StringUtils.hasLength(targetUrl)) {
+            targetUrl = request.getHeader("Referer");
+            logger.debug("Using Referer header: " + targetUrl);
+        }
+
+        if (!StringUtils.hasText(targetUrl)) {
+            targetUrl = defaultTargetUrl;
+            logger.debug("Using default Url: " + targetUrl);
+        }
+
+        return targetUrl;
+    }
+
+    /**
+     * Supplies the default target Url that will be used if no saved request is found or the
+     * <tt>alwaysUseDefaultTargetUrl</tt> property is set to true. If not set, defaults to <tt>/</tt>.
+     *
+     * @return the defaultTargetUrl property
+     */
+    protected String getDefaultTargetUrl() {
+        return defaultTargetUrl;
+    }
+
+    /**
+     * Supplies the default target Url that will be used if no saved request is found in the session, or the
+     * <tt>alwaysUseDefaultTargetUrl</tt> property is set to true. If not set, defaults to <tt>/</tt>. It
+     * will be treated as relative to the web-app's context path, and should include the leading <code>/</code>.
+     * Alternatively, inclusion of a scheme name (such as "http://" or "https://") as the prefix will denote a
+     * fully-qualified URL and this is also supported.
+     *
+     * @param defaultTargetUrl
+     */
+    public void setDefaultTargetUrl(String defaultTargetUrl) {
+        Assert.isTrue(UrlUtils.isValidRedirectUrl(defaultTargetUrl),
+                "defaultTarget must start with '/' or with 'http(s)'");
+        this.defaultTargetUrl = defaultTargetUrl;
+    }
+
+    /**
+     * If <code>true</code>, will always redirect to the value of <tt>defaultTargetUrl</tt>
+     * (defaults to <code>false</code>).
+     */
+    public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) {
+        this.alwaysUseDefaultTargetUrl = alwaysUseDefaultTargetUrl;
+    }
+
+    protected boolean isAlwaysUseDefaultTargetUrl() {
+        return alwaysUseDefaultTargetUrl;
+    }
+
+    /**
+     * The current request will be checked for this parameter before and the value used as the target URL if resent.
+     *
+     *  @param targetUrlParameter the name of the parameter containing the encoded target URL. Defaults
+     *  to "redirect".
+     */
+    public void setTargetUrlParameter(String targetUrlParameter) {
+        Assert.hasText("targetUrlParameter canot be null or empty");
+        this.targetUrlParameter = targetUrlParameter;
+    }
+
+    protected String getTargetUrlParameter() {
+        return targetUrlParameter;
+    }
+
+    /**
+     * If <tt>true</tt>, causes any redirection URLs to be calculated minus the protocol
+     * and context path (defaults to <tt>false</tt>).
+     */
+    public void setUseRelativeContext(boolean useRelativeContext) {
+        this.useRelativeContext = useRelativeContext;
+    }
+
+    protected boolean isUseRelativeContext() {
+        return useRelativeContext;
+    }
+
+    /**
+     * If set to <tt>true</tt> the <tt>Referer</tt> header will be used (if available). Defaults to <tt>false</tt>.
+     */
+    public void setUseReferer(boolean useReferer) {
+        this.useReferer = useReferer;
+    }
+}

+ 29 - 0
core/src/main/java/org/springframework/security/ui/LogoutSuccessHandler.java

@@ -0,0 +1,29 @@
+package org.springframework.security.ui;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.Authentication;
+import org.springframework.security.ui.logout.LogoutFilter;
+
+/**
+ * Strategy that is called after a successful logout by the {@link LogoutFilter}, to handle redirection or
+ * forwarding to the appropriate destination.
+ * <p>
+ * Note that the interface is almost the same as {@link LogoutHandler} but may raise an exception.
+ * <tt>LogoutHandler</tt> implementations expect to be invoked to perform necessary cleanup, so should not throw
+ * exceptions.
+ *
+ * @author Luke Taylor
+ * @version $Id$
+ * @since 2.5
+ */
+public interface LogoutSuccessHandler {
+
+    void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+            throws IOException, ServletException;
+
+}

+ 10 - 6
core/src/main/java/org/springframework/security/ui/SavedRequestAwareAuthenticationSuccessHandler.java

@@ -14,9 +14,13 @@ import org.springframework.security.wrapper.SavedRequestAwareWrapper;
 import org.springframework.util.StringUtils;
 
 /**
- * Decides on the redirect destination following a successful authentication, based on the following
- * configuration options:
- *
+ * An authentication success strategy which can make use of the {@link SavedRequest} which may have been stored in
+ * the session by the {@link ExceptionTranslationFilter}. When such a request is intercepted and requires authentication,
+ * the request data is stored to record the original destination before the authentication process commenced, and to
+ * allow the request to be reconstructed when a redirect to the same URL occurs. This class is responsible for
+ * performing the redirect to the original URL if appropriate.
+ * <p>
+ * Following a successful authentication, it decides on the redirect destination, based on the following scenarios:
  * <ul>
  * <li>
  * If the <tt>alwaysUseDefaultTargetUrl</tt> property is set to true, the <tt>defaultTargetUrl</tt>
@@ -34,7 +38,7 @@ import org.springframework.util.StringUtils;
  * when the redirected request is received (See {@link SavedRequestAwareWrapper}).
  * </li>
  * <li>
- * Fall back to the <tt>defaultTargetUrl</tt>
+ * If no <tt>SavedRequest</tt> is found in the session, it will delegate to the base class.
  * </li>
  * </ul>
  *
@@ -56,7 +60,7 @@ public class SavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuth
             return;
         }
 
-        if (isAlwaysUseDefaultTargetUrl() || StringUtils.hasText(request.getParameter(targetUrlParameter))) {
+        if (isAlwaysUseDefaultTargetUrl() || StringUtils.hasText(request.getParameter(getTargetUrlParameter()))) {
             removeSavedRequest(request);
             super.onAuthenticationSuccess(request, response, authentication);
 
@@ -66,7 +70,7 @@ public class SavedRequestAwareAuthenticationSuccessHandler extends SimpleUrlAuth
         // Use the SavedRequest URL
         String targetUrl = savedRequest.getFullRequestUrl();
         logger.debug("Redirecting to SavedRequest Url: " + targetUrl);
-        RedirectUtils.sendRedirect(request, response, targetUrl, useRelativeContext);
+        RedirectUtils.sendRedirect(request, response, targetUrl, isUseRelativeContext());
     }
 
     private SavedRequest getSavedRequest(HttpServletRequest request) {

+ 1 - 1
core/src/main/java/org/springframework/security/ui/SimpleUrlAuthenticationFailureHandler.java

@@ -18,7 +18,7 @@ import org.springframework.util.Assert;
  * <tt>AuthenticationException</tt> which caused the failure.
  * <p>
  * If the <tt>forwardToDestination</tt> parameter is set, a <tt>RequestDispatcher.forward</tt> call will be made to
- * the destination instead of
+ * the destination instead of a redirect.
  *
  * @author Luke Taylor
  * @version $Id$

+ 2 - 101
core/src/main/java/org/springframework/security/ui/SimpleUrlAuthenticationSuccessHandler.java

@@ -1,29 +1,14 @@
 package org.springframework.security.ui;
 
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.URLDecoder;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.springframework.security.Authentication;
-import org.springframework.security.util.RedirectUtils;
-import org.springframework.security.util.UrlUtils;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
 
-public class SimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
-
-    public static String DEFAULT_TARGET_PARAMETER = "spring-security-redirect";
-    protected final Log logger = LogFactory.getLog(this.getClass());
-    protected String targetUrlParameter = DEFAULT_TARGET_PARAMETER;
-    protected String defaultTargetUrl = "/";
-    protected boolean alwaysUseDefaultTargetUrl = false;
-    protected boolean useRelativeContext = false;
+public class SimpleUrlAuthenticationSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler implements AuthenticationSuccessHandler {
 
     public SimpleUrlAuthenticationSuccessHandler() {
     }
@@ -35,90 +20,6 @@ public class SimpleUrlAuthenticationSuccessHandler implements AuthenticationSucc
     public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
             Authentication authentication) throws IOException, ServletException {
 
-        if (isAlwaysUseDefaultTargetUrl()) {
-            RedirectUtils.sendRedirect(request, response, getDefaultTargetUrl(), useRelativeContext);
-            return;
-        }
-
-        // Check for the parameter and use that if available
-        String targetUrl = request.getParameter(targetUrlParameter);
-
-        if (StringUtils.hasText(targetUrl)) {
-            try {
-                targetUrl = URLDecoder.decode(targetUrl, "UTF-8");
-            } catch (UnsupportedEncodingException e) {
-                throw new IllegalStateException("UTF-8 not supported. Shouldn't be possible");
-            }
-
-            logger.debug("Found targetUrlParameter in request. Redirecting to: " + targetUrl);
-
-            RedirectUtils.sendRedirect(request, response, targetUrl, useRelativeContext);
-
-            return;
-        }
-
-        if (targetUrl == null) {
-            targetUrl = getDefaultTargetUrl();
-            logger.debug("Redirecting to default Url: " + targetUrl);
-        }
-
-        RedirectUtils.sendRedirect(request, response, targetUrl, useRelativeContext);
-    }
-
-    /**
-     * Supplies the default target Url that will be used if no saved request is found or the
-     * <tt>alwaysUseDefaultTargetUrl</tt> property is set to true. If not set, defaults to <tt>/</tt>.
-     *
-     * @return the defaultTargetUrl property
-     */
-    protected String getDefaultTargetUrl() {
-        return defaultTargetUrl;
-    }
-
-    /**
-     * Supplies the default target Url that will be used if no saved request is found in the session, or the
-     * <tt>alwaysUseDefaultTargetUrl</tt> property is set to true. If not set, defaults to <tt>/</tt>. It
-     * will be treated as relative to the web-app's context path, and should include the leading <code>/</code>.
-     * Alternatively, inclusion of a scheme name (such as "http://" or "https://") as the prefix will denote a
-     * fully-qualified URL and this is also supported.
-     *
-     * @param defaultTargetUrl
-     */
-    public void setDefaultTargetUrl(String defaultTargetUrl) {
-        Assert.isTrue(UrlUtils.isValidRedirectUrl(defaultTargetUrl),
-                "defaultTarget must start with '/' or with 'http(s)'");
-        this.defaultTargetUrl = defaultTargetUrl;
-    }
-
-    /**
-     * If <code>true</code>, will always redirect to the value of <tt>defaultTargetUrl</tt>
-     * (defaults to <code>false</code>).
-     */
-    public void setAlwaysUseDefaultTargetUrl(boolean alwaysUseDefaultTargetUrl) {
-        this.alwaysUseDefaultTargetUrl = alwaysUseDefaultTargetUrl;
-    }
-
-    protected boolean isAlwaysUseDefaultTargetUrl() {
-        return alwaysUseDefaultTargetUrl;
-    }
-
-    /**
-     * Before checking the SavedRequest, the current request will be checked for this parameter
-     * and the value used as the target URL if resent.
-     *
-     *  @param targetUrlParameter the name of the parameter containing the encoded target URL. Defaults
-     *  to "redirect".
-     */
-    public void setTargetUrlParameter(String targetUrlParameter) {
-        Assert.hasText("targetUrlParameter canot be null or empty");
-        this.targetUrlParameter = targetUrlParameter;
-    }
-
-    /**
-     * If <tt>true</tt>, causes any redirection URLs to be calculated minus the protocol
-     * and context path (defaults to <tt>false</tt>).
-     */
-    public void setUseRelativeContext(boolean useRelativeContext) {
-        this.useRelativeContext = useRelativeContext;
+        handle(request, response, authentication);
     }
 }

+ 36 - 71
core/src/main/java/org/springframework/security/ui/logout/LogoutFilter.java

@@ -16,6 +16,8 @@
 package org.springframework.security.ui.logout;
 
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
 
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
@@ -23,11 +25,11 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.springframework.security.Authentication;
-import org.springframework.security.ui.SpringSecurityFilter;
+import org.springframework.security.context.SecurityContextHolder;
 import org.springframework.security.ui.FilterChainOrder;
-import org.springframework.security.util.RedirectUtils;
+import org.springframework.security.ui.LogoutSuccessHandler;
+import org.springframework.security.ui.SpringSecurityFilter;
 import org.springframework.security.util.UrlUtils;
-import org.springframework.security.context.SecurityContextHolder;
 import org.springframework.util.Assert;
 import org.springframework.util.StringUtils;
 
@@ -37,11 +39,10 @@ import org.springframework.util.StringUtils;
  * Polls a series of {@link LogoutHandler}s. The handlers should be specified in the order they are required.
  * Generally you will want to call logout handlers <code>TokenBasedRememberMeServices</code> and
  * <code>SecurityContextLogoutHandler</code> (in that order).
- * </p>
  * <p>
- * After logout, the URL specified by {@link #logoutSuccessUrl} will be shown.
- * </p>
- * 
+ * After logout, a redirect will be performed to the URL determined by either the configured
+ * <tt>LogoutSuccessHandler</tt> or the <tt>logoutSuccessUrl</tt>, depending on which constructor was used.
+ *
  * @author Ben Alex
  * @version $Id$
  */
@@ -50,17 +51,32 @@ public class LogoutFilter extends SpringSecurityFilter {
     //~ Instance fields ================================================================================================
 
     private String filterProcessesUrl = "/j_spring_security_logout";
-    private String logoutSuccessUrl;
-    private LogoutHandler[] handlers;
-    private boolean useRelativeContext;
+    private List<LogoutHandler> handlers;    private LogoutSuccessHandler logoutSuccessHandler;
 
     //~ Constructors ===================================================================================================
 
-    public LogoutFilter(String logoutSuccessUrl, LogoutHandler[] handlers) {
+    /**
+     * Constructor which takes a <tt>LogoutSuccessHandler</tt> instance to determine the target destination
+     * after logging out. The list of <tt>LogoutHandler</tt>s are intended to perform the actual logout functionality
+     * (such as clearing the security context, invalidating the session, etc.).
+     */
+    public LogoutFilter(LogoutSuccessHandler logoutSuccessHandler, LogoutHandler... handlers) {
         Assert.notEmpty(handlers, "LogoutHandlers are required");
-        this.logoutSuccessUrl = logoutSuccessUrl;
-        Assert.isTrue(UrlUtils.isValidRedirectUrl(logoutSuccessUrl), logoutSuccessUrl + " isn't a valid redirect URL");
-        this.handlers = handlers;
+        this.handlers = Arrays.asList(handlers);
+        Assert.notNull(logoutSuccessHandler, "logoutSuccessHandler cannot be null");
+        this.logoutSuccessHandler = logoutSuccessHandler;
+    }
+
+    public LogoutFilter(String logoutSuccessUrl, LogoutHandler... handlers) {
+        Assert.notEmpty(handlers, "LogoutHandlers are required");
+        this.handlers = Arrays.asList(handlers);
+        Assert.isTrue(!StringUtils.hasLength(logoutSuccessUrl) ||
+                UrlUtils.isValidRedirectUrl(logoutSuccessUrl), logoutSuccessUrl + " isn't a valid redirect URL");
+        SimpleUrlLogoutSuccessHandler urlLogoutSuccessHandler = new SimpleUrlLogoutSuccessHandler();
+        if (StringUtils.hasText(logoutSuccessUrl)) {
+            urlLogoutSuccessHandler.setDefaultTargetUrl(logoutSuccessUrl);
+        }
+        logoutSuccessHandler = urlLogoutSuccessHandler;
     }
 
     //~ Methods ========================================================================================================
@@ -72,16 +88,14 @@ public class LogoutFilter extends SpringSecurityFilter {
             Authentication auth = SecurityContextHolder.getContext().getAuthentication();
 
             if (logger.isDebugEnabled()) {
-                logger.debug("Logging out user '" + auth + "' and redirecting to logout page");
+                logger.debug("Logging out user '" + auth + "' and transferring to logout destination");
             }
 
-            for (int i = 0; i < handlers.length; i++) {
-                handlers[i].logout(request, response, auth);
+            for (LogoutHandler handler : handlers) {
+                handler.logout(request, response, auth);
             }
 
-            String targetUrl = determineTargetUrl(request, response);
-
-            sendRedirect(request, response, targetUrl);
+            logoutSuccessHandler.onLogoutSuccess(request, response, auth);
 
             return;
         }
@@ -120,65 +134,16 @@ public class LogoutFilter extends SpringSecurityFilter {
         return uri.endsWith(request.getContextPath() + filterProcessesUrl);
     }
 
-    /**
-     * Returns the target URL to redirect to after logout.
-     * <p>
-     * By default it will check for a <tt>logoutSuccessUrl</tt> parameter in
-     * the request and use this. If that isn't present it will use the configured <tt>logoutSuccessUrl</tt>. If this
-     * hasn't been set it will check the Referer header and use the URL from there.
-     *
-     */
-    protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) {
-        String targetUrl = request.getParameter("logoutSuccessUrl");
-
-        if(!StringUtils.hasLength(targetUrl)) {
-            targetUrl = getLogoutSuccessUrl();
-        }
-
-        if (!StringUtils.hasLength(targetUrl)) {
-            targetUrl = request.getHeader("Referer");
-        }        
-
-        if (!StringUtils.hasLength(targetUrl)) {
-            targetUrl = "/";
-        }
-
-        return targetUrl;
-    }
-
-    /**
-     * Allow subclasses to modify the redirection message.
-     *
-     * @param request  the request
-     * @param response the response
-     * @param url      the URL to redirect to
-     *
-     * @throws IOException in the event of any failure
-     */
-    protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
-            throws IOException {
-
-        RedirectUtils.sendRedirect(request, response, url, useRelativeContext);
-    }
-
     public void setFilterProcessesUrl(String filterProcessesUrl) {
-        Assert.hasText(filterProcessesUrl, "FilterProcessesUrl required");
-        Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid redirect URL");
+        Assert.isTrue(UrlUtils.isValidRedirectUrl(filterProcessesUrl), filterProcessesUrl + " isn't a valid value for" +
+                " 'filterProcessesUrl'");
         this.filterProcessesUrl = filterProcessesUrl;
     }
 
-    protected String getLogoutSuccessUrl() {
-        return logoutSuccessUrl;
-    }    
-    
     protected String getFilterProcessesUrl() {
         return filterProcessesUrl;
     }
 
-    public void setUseRelativeContext(boolean useRelativeContext) {
-        this.useRelativeContext = useRelativeContext;
-    }
-
     public int getOrder() {
         return FilterChainOrder.LOGOUT_FILTER;
     }

+ 29 - 0
core/src/main/java/org/springframework/security/ui/logout/SimpleUrlLogoutSuccessHandler.java

@@ -0,0 +1,29 @@
+package org.springframework.security.ui.logout;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.springframework.security.Authentication;
+import org.springframework.security.ui.AbstractAuthenticationTargetUrlRequestHandler;
+import org.springframework.security.ui.LogoutSuccessHandler;
+
+/**
+ * Handles the navigation on logout by delegating to the {@link AbstractAuthenticationTargetUrlRequestHandler}
+ * base class logic.
+ *
+ * @author Luke Taylor
+ * @version $Id$
+ * @since 2.5
+ */
+public class SimpleUrlLogoutSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler
+        implements LogoutSuccessHandler {
+
+    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+            throws IOException, ServletException {
+        super.handle(request, response, authentication);
+    }
+
+}

+ 4 - 3
core/src/test/java/org/springframework/security/config/HttpSecurityBeanDefinitionParserTests.java

@@ -395,6 +395,7 @@ public class HttpSecurityBeanDefinitionParserTests {
     }
 
     @Test
+    @SuppressWarnings("unchecked")
     public void rememberMeServiceWorksWithExternalServicesImpl() throws Exception {
         setContext(
                 "<http auto-config='true'>" +
@@ -410,9 +411,9 @@ public class HttpSecurityBeanDefinitionParserTests {
         assertEquals(5000, FieldUtils.getFieldValue(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES),
                 "tokenValiditySeconds"));
         // SEC-909
-        LogoutHandler[] logoutHandlers = (LogoutHandler[]) FieldUtils.getFieldValue(appContext.getBean(BeanIds.LOGOUT_FILTER), "handlers");
-        assertEquals(2, logoutHandlers.length);
-        assertEquals(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES), logoutHandlers[1]);
+        List<LogoutHandler> logoutHandlers = (List<LogoutHandler>) FieldUtils.getFieldValue(appContext.getBean(BeanIds.LOGOUT_FILTER), "handlers");
+        assertEquals(2, logoutHandlers.size());
+        assertEquals(appContext.getBean(BeanIds.REMEMBER_ME_SERVICES), logoutHandlers.get(1));
     }
 
     @Test

+ 1 - 1
core/src/test/java/org/springframework/security/ui/logout/LogoutHandlerTests.java

@@ -13,7 +13,7 @@ public class LogoutHandlerTests extends TestCase {
     LogoutFilter filter;
 
     protected void setUp() throws Exception {
-        filter = new LogoutFilter("/success", new LogoutHandler[] {new SecurityContextLogoutHandler()});
+        filter = new LogoutFilter("/success", new SecurityContextLogoutHandler());
     }
 
     public void testRequiresLogoutUrlWorksWithPathParams() {

+ 18 - 0
itest/web/src/main/webapp/WEB-INF/classes/log4j.properties

@@ -0,0 +1,18 @@
+# Global logging configuration
+log4j.rootLogger=INFO, stdout, fileout
+
+log4j.logger.org.springframework.security=DEBUG
+
+# Console output...
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.conversionPattern=[%p,%c{1},%t] %m%n
+
+# Rolling log file output...
+log4j.appender.fileout=org.apache.log4j.FileAppender
+log4j.appender.fileout.File=itest-web.log
+log4j.appender.fileout.Append=false
+log4j.appender.fileout.layout=org.apache.log4j.PatternLayout
+log4j.appender.fileout.layout.conversionPattern=%d{ABSOLUTE} %5p %c{1},%t:%L - %m%n
+
+

+ 4 - 4
itest/web/src/test/java/org/springframework/security/integration/InMemoryProviderWebAppTests.java

@@ -11,7 +11,7 @@ public class InMemoryProviderWebAppTests extends AbstractWebServerIntegrationTes
     protected String getContextConfigLocations() {
         return "/WEB-INF/http-security.xml /WEB-INF/in-memory-provider.xml";
     }
-    
+
     @Test
     public void loginFailsWithinvalidPassword() {
         beginAt("secure/index.html");
@@ -22,11 +22,11 @@ public class InMemoryProviderWebAppTests extends AbstractWebServerIntegrationTes
     @Test
     public void loginSucceedsWithCorrectPassword() {
         beginAt("secure/index.html");
-        login("jimi", "jimispassword");        
+        login("jimi", "jimispassword");
         assertTextPresent("A Secure Page");
         tester.gotoPage("/logout");
     }
-    
+
     /*
      * Checks use of <jsp:include> with parameters in the secured page.
      */
@@ -39,4 +39,4 @@ public class InMemoryProviderWebAppTests extends AbstractWebServerIntegrationTes
         assertTextPresent("xcount=2");
     }
 
-}
+}