Răsfoiți Sursa

SEC-414: Add useRelativeContext and sendRedirectMethod to SwitchUserProcessingFilter.

Luke Taylor 17 ani în urmă
părinte
comite
f983ff204d

+ 21 - 2
core/src/main/java/org/springframework/security/ui/switchuser/SwitchUserProcessingFilter.java

@@ -24,6 +24,7 @@ import org.springframework.security.CredentialsExpiredException;
 import org.springframework.security.DisabledException;
 import org.springframework.security.GrantedAuthority;
 import org.springframework.security.LockedException;
+import org.springframework.security.util.RedirectUtils;
 
 import org.springframework.security.context.SecurityContextHolder;
 
@@ -35,6 +36,7 @@ import org.springframework.security.ui.AuthenticationDetailsSource;
 import org.springframework.security.ui.AuthenticationDetailsSourceImpl;
 import org.springframework.security.ui.SpringSecurityFilter;
 import org.springframework.security.ui.FilterChainOrderUtils;
+import org.springframework.security.ui.AbstractProcessingFilter;
 
 import org.springframework.security.userdetails.UserDetails;
 import org.springframework.security.userdetails.UserDetailsService;
@@ -120,6 +122,7 @@ public class SwitchUserProcessingFilter extends SpringSecurityFilter implements
     private String targetUrl;
     private SwitchUserAuthorityChanger switchUserAuthorityChanger;
     private UserDetailsService userDetailsService;
+    private boolean useRelativeContext;
 
     //~ Methods ========================================================================================================
 
@@ -311,7 +314,7 @@ public class SwitchUserProcessingFilter extends SpringSecurityFilter implements
             SecurityContextHolder.getContext().setAuthentication(targetUser);
 
             // redirect to target url
-            response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + targetUrl));
+            sendRedirect(request, response, targetUrl);
 
             return;
         } else if (requiresExitUser(request)) {
@@ -322,7 +325,7 @@ public class SwitchUserProcessingFilter extends SpringSecurityFilter implements
             SecurityContextHolder.getContext().setAuthentication(originalUser);
 
             // redirect to target url
-            response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + targetUrl));
+            sendRedirect(request, response, targetUrl);
 
             return;
         }
@@ -330,6 +333,12 @@ public class SwitchUserProcessingFilter extends SpringSecurityFilter implements
         chain.doFilter(request, response);
     }
 
+    protected void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url)
+            throws IOException {
+
+        RedirectUtils.sendRedirect(request, response, url, useRelativeContext);
+    }
+
     /**
      * Find the original <code>Authentication</code> object from the current user's granted authorities. A
      * successfully switched user should have a <code>SwitchUserGrantedAuthority</code> that contains the original
@@ -436,6 +445,16 @@ public class SwitchUserProcessingFilter extends SpringSecurityFilter implements
         this.userDetailsService = userDetailsService;
     }
 
+    /**
+     * Analogous to the same property in {@link AbstractProcessingFilter}. If set, redirects will
+     * be context-relative (they won't include the context path).
+     *
+     * @param useRelativeContext
+     */
+    public void setUseRelativeContext(boolean useRelativeContext) {
+        this.useRelativeContext = useRelativeContext;
+    }
+
     /**
      * Strips any content after the ';' in the request URI
      *

+ 28 - 1
core/src/test/java/org/springframework/security/ui/switchuser/SwitchUserProcessingFilterTests.java

@@ -260,6 +260,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
         SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
         filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
         filter.setExitUserUrl("/j_spring_security_exit_user");
+        filter.setTargetUrl("/webapp/someOtherUrl");
 
         MockFilterChain chain = new MockFilterChain(true);
 
@@ -304,6 +305,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
         SecurityContextHolder.getContext().setAuthentication(auth);
 
         MockHttpServletRequest request = createMockSwitchRequest();
+        request.setContextPath("/webapp");
         request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
         request.setRequestURI("/webapp/j_spring_security_switch_user");
 
@@ -312,7 +314,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
 
         SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
         filter.setSwitchUserUrl("/j_spring_security_switch_user");
-        filter.setTargetUrl("/webapp/someOtherUrl");
+        filter.setTargetUrl("/someOtherUrl");
         filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
 
         filter.doFilter(request, response, chain);
@@ -320,6 +322,30 @@ public class SwitchUserProcessingFilterTests extends TestCase {
         assertEquals("/webapp/someOtherUrl", response.getRedirectedUrl());
     }
 
+    public void testRedirectOmitsContextPathIfUseRelativeContextSet() throws Exception {
+        // set current user
+        UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("dano", "hawaii50");
+        SecurityContextHolder.getContext().setAuthentication(auth);
+
+        MockHttpServletRequest request = createMockSwitchRequest();
+        request.setContextPath("/webapp");
+        request.addParameter(SwitchUserProcessingFilter.SPRING_SECURITY_SWITCH_USERNAME_KEY, "jacklord");
+        request.setRequestURI("/webapp/j_spring_security_switch_user");
+
+        MockHttpServletResponse response = new MockHttpServletResponse();
+        MockFilterChain chain = new MockFilterChain(true);
+
+        SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
+        filter.setSwitchUserUrl("/j_spring_security_switch_user");
+        filter.setTargetUrl("/someOtherUrl");
+        filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
+        filter.setUseRelativeContext(true);
+
+        filter.doFilter(request, response, chain);
+
+        assertEquals("/someOtherUrl", response.getRedirectedUrl());
+    }
+
     public void testRequiresExitUser() {
         // filter
         SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
@@ -360,6 +386,7 @@ public class SwitchUserProcessingFilterTests extends TestCase {
         SwitchUserProcessingFilter filter = new SwitchUserProcessingFilter();
         filter.setUserDetailsService(new MockAuthenticationDaoUserJackLord());
         filter.setSwitchUserUrl("/j_spring_security_switch_user");
+        filter.setTargetUrl("/webapp/someOtherUrl");
 
         MockFilterChain chain = new MockFilterChain(true);