From e6e1f2586f62d69ad273927ab7432d4ddf7705e8 Mon Sep 17 00:00:00 2001 From: Luke Taylor Date: Thu, 28 Feb 2008 11:03:05 +0000 Subject: [PATCH] SEC-213: Allow custom redirects based on "redirect" parameter in AbstractProcessingFilter. successfulAuthentication() http://jira.springframework.org/browse/SEC-213 --- .../security/ui/TargetUrlResolver.java | 4 +- .../security/ui/TargetUrlResolverImpl.java | 44 +++++++++++++++++-- .../ui/AbstractProcessingFilterTests.java | 23 ++++++++++ 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/org/springframework/security/ui/TargetUrlResolver.java b/core/src/main/java/org/springframework/security/ui/TargetUrlResolver.java index 1b12547df6..7cd95d0461 100644 --- a/core/src/main/java/org/springframework/security/ui/TargetUrlResolver.java +++ b/core/src/main/java/org/springframework/security/ui/TargetUrlResolver.java @@ -22,7 +22,7 @@ import org.springframework.security.ui.savedrequest.SavedRequest; /** * Used by {@link AbstractProcessingFilter} to determine target URL in case of - * successfull authentication. + * successful authentication. * * @author Martino Piccinato * @version $Id$ @@ -34,7 +34,7 @@ public interface TargetUrlResolver { /** * @param savedRequest The request that initiated the authentication process * @param currentRequest the current request - * @param auth The authentication token generated after successfull authentication + * @param auth The authentication token generated after successful authentication * @return The URL to be used */ public String determineTargetUrl(SavedRequest savedRequest, HttpServletRequest currentRequest, Authentication auth); diff --git a/core/src/main/java/org/springframework/security/ui/TargetUrlResolverImpl.java b/core/src/main/java/org/springframework/security/ui/TargetUrlResolverImpl.java index 176ee647cd..ef10dd1ecb 100644 --- a/core/src/main/java/org/springframework/security/ui/TargetUrlResolverImpl.java +++ b/core/src/main/java/org/springframework/security/ui/TargetUrlResolverImpl.java @@ -15,26 +15,38 @@ package org.springframework.security.ui; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + import javax.servlet.http.HttpServletRequest; import org.springframework.security.Authentication; import org.springframework.security.ui.savedrequest.SavedRequest; +import org.springframework.util.StringUtils; /** * Default implementation for {@link TargetUrlResolver} + *

+ * Returns a target URL based from the contents of the configured targetUrlParameter if present on + * the current request. Failing that, the SavedRequest in the session will be used. * * @author Martino Piccinato + * @author Luke Taylor * @version $Id$ * @since 2.0 * */ public class TargetUrlResolverImpl implements TargetUrlResolver { + public static String DEFAULT_TARGET_PARAMETER = "redirect"; + + /* SEC-213 */ + private String targetUrlParameter; /** - * If true, will only use SavedRequest to determine the target url on successful + * If true, will only use SavedRequest to determine the target URL on successful * authentication if the request that caused the authentication request was a GET. - * It will return null on POST/PUT request. - * In most cases it's meaningless to redirect to a Url generated by a POST/PUT request. + * It will return null for a POST/PUT request. + * In most cases it's meaningless to redirect to a URL generated by a POST/PUT request. * Defaults to true. */ private boolean justUseSavedRequestOnGet = true; @@ -46,6 +58,18 @@ public class TargetUrlResolverImpl implements TargetUrlResolver { Authentication auth) { String targetUrl = null; + + if (targetUrlParameter != null) { + targetUrl = currentRequest.getParameter(targetUrlParameter); + + if (StringUtils.hasText(targetUrl)) { + try { + return URLDecoder.decode(targetUrl, "UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new IllegalStateException("UTF-8 not supported. Shouldn't be possible"); + } + } + } if (savedRequest != null) { if (!justUseSavedRequestOnGet || savedRequest.getMethod().equals("GET")) { @@ -72,5 +96,19 @@ public class TargetUrlResolverImpl implements TargetUrlResolver { public void setJustUseSavedRequestOnGet(boolean justUseSavedRequestOnGet) { this.justUseSavedRequestOnGet = justUseSavedRequestOnGet; } + + + /** + * 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) { + this.targetUrlParameter = targetUrlParameter; + } + + } diff --git a/core/src/test/java/org/springframework/security/ui/AbstractProcessingFilterTests.java b/core/src/test/java/org/springframework/security/ui/AbstractProcessingFilterTests.java index e3b857265d..ecc3cc74bb 100644 --- a/core/src/test/java/org/springframework/security/ui/AbstractProcessingFilterTests.java +++ b/core/src/test/java/org/springframework/security/ui/AbstractProcessingFilterTests.java @@ -571,6 +571,29 @@ public class AbstractProcessingFilterTests extends TestCase { assertEquals("/error", response.getForwardedUrl()); } + /** + * SEC-213 + */ + public void testTargetUrlParameterIsUsedIfPresent() throws Exception { + MockHttpServletRequest request = createMockRequest(); + request.setParameter("targetUrl", "/target"); + + MockFilterConfig config = new MockFilterConfig(null, null); + MockFilterChain chain = new MockFilterChain(true); + MockHttpServletResponse response = new MockHttpServletResponse(); + + MockAbstractProcessingFilter filter = new MockAbstractProcessingFilter(true); + TargetUrlResolverImpl targetUrlResolver = new TargetUrlResolverImpl(); + targetUrlResolver.setTargetUrlParameter("targetUrl"); + filter.setTargetUrlResolver(targetUrlResolver); + filter.setDefaultTargetUrl("http://monkeymachine.co.uk/"); + filter.setAuthenticationFailureUrl("/error"); + + executeFilterInContainerSimulator(config, filter, request, response, chain); + + assertEquals("/mycontext/target", response.getRedirectedUrl()); + } + //~ Inner Classes ==================================================================================================