Procházet zdrojové kódy

SEC-1052: Added "disableUrlRewriting" parameter to HttpSessionSecurityContextRepository.

Luke Taylor před 16 roky
rodič
revize
b24cc17dea

+ 12 - 1
core/src/main/java/org/springframework/security/context/HttpSessionSecurityContextRepository.java

@@ -61,6 +61,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
     private Object contextObject = new SecurityContextImpl();
     private boolean cloneFromHttpSession = false;
     private boolean allowSessionCreation = true;
+    private boolean disableUrlRewriting = false;
 
     private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
 
@@ -234,6 +235,16 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
         this.allowSessionCreation = allowSessionCreation;
     }
 
+    /**
+     * Allows the use of session identifiers in URLs to be disabled. Off by default.
+     *
+     * @param disableUrlRewriting set to <tt>true</tt> to disable URL encoding methods in the response wrapper
+     *                            and prevent the use of <tt>jsessionid</tt> parameters.
+     */
+    public void setDisableUrlRewriting(boolean disableUrlRewriting) {
+        this.disableUrlRewriting = disableUrlRewriting;
+    }
+
     //~ Inner Classes ==================================================================================================
 
     /**
@@ -265,7 +276,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
         SaveToSessionResponseWrapper(HttpServletResponse response, HttpServletRequest request,
                                                       boolean httpSessionExistedAtStartOfRequest,
                                                       int contextHashBeforeChainExecution) {
-            super(response);
+            super(response, disableUrlRewriting);
             this.request = request;
             this.httpSessionExistedAtStartOfRequest = httpSessionExistedAtStartOfRequest;
             this.contextHashBeforeChainExecution = contextHashBeforeChainExecution;

+ 53 - 8
core/src/main/java/org/springframework/security/context/SaveContextOnUpdateOrErrorResponseWrapper.java

@@ -8,21 +8,31 @@ import javax.servlet.http.HttpServletResponseWrapper;
 /**
  * Base class for response wrappers which encapsulate the logic for storing a security context and which
  * store the with the <code>SecurityContext</code> when a <code>sendError()</code> or <code>sendRedirect</code>
- * happens. See SEC-398.
+ * happens. See issue SEC-398.
  * <p>
  * Sub-classes should implement the {@link #saveContext(SecurityContext context)} method.
+ * <p>
+ * Support is also provided for disabling URL rewriting
  *
  * @author Luke Taylor
  * @author Marten Algesten
  * @version $Id$
  * @since 2.5
  */
-abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResponseWrapper {
+public abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResponseWrapper {
 
-    boolean contextSaved = false;
+    private boolean contextSaved = false;
+    /* See SEC-1052 */
+    private boolean disableUrlRewriting;
 
-    SaveContextOnUpdateOrErrorResponseWrapper(HttpServletResponse response) {
+    /**
+     * @param response              the response to be wrapped
+     * @param disableUrlRewriting   turns the URL encoding methods into null operations, preventing the use
+     *                              of URL rewriting to add the session identifier as a URL parameter.
+     */
+    public SaveContextOnUpdateOrErrorResponseWrapper(HttpServletResponse response, boolean disableUrlRewriting) {
         super(response);
+        this.disableUrlRewriting = disableUrlRewriting;
     }
 
     /**
@@ -36,7 +46,8 @@ abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResp
      * Makes sure the session is updated before calling the
      * superclass <code>sendError()</code>
      */
-    public void sendError(int sc) throws IOException {
+    @Override
+    public final void sendError(int sc) throws IOException {
         doSaveContext();
         super.sendError(sc);
     }
@@ -45,7 +56,8 @@ abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResp
      * Makes sure the session is updated before calling the
      * superclass <code>sendError()</code>
      */
-    public void sendError(int sc, String msg) throws IOException {
+    @Override
+    public final void sendError(int sc, String msg) throws IOException {
         doSaveContext();
         super.sendError(sc, msg);
     }
@@ -54,7 +66,8 @@ abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResp
      * Makes sure the context is stored before calling the
      * superclass <code>sendRedirect()</code>
      */
-    public void sendRedirect(String location) throws IOException {
+    @Override
+    public final void sendRedirect(String location) throws IOException {
         doSaveContext();
         super.sendRedirect(location);
     }
@@ -67,10 +80,42 @@ abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResp
         contextSaved = true;
     }
 
+    @Override
+    public final String encodeRedirectUrl(String url) {
+        if (disableUrlRewriting) {
+            return url;
+        }
+        return super.encodeRedirectUrl(url);
+    }
+
+    @Override
+    public final String encodeRedirectURL(String url) {
+        if (disableUrlRewriting) {
+            return url;
+        }
+        return super.encodeRedirectURL(url);
+    }
+
+    @Override
+    public final String encodeUrl(String url) {
+        if (disableUrlRewriting) {
+            return url;
+        }
+        return super.encodeUrl(url);
+    }
+
+    @Override
+    public final String encodeURL(String url) {
+        if (disableUrlRewriting) {
+            return url;
+        }
+        return super.encodeURL(url);
+    }
+
     /**
      * Tells if the response wrapper has called <code>saveContext()</code> because of an error or redirect.
      */
-    public boolean isContextSaved() {
+    public final boolean isContextSaved() {
         return contextSaved;
     }
 

+ 5 - 4
core/src/main/java/org/springframework/security/context/package.html

@@ -1,10 +1,11 @@
 <html>
 <body>
-Provides a "request context".
+Classes related to the establishment of a security context for the duration of a request (such as
+an HTTP or RMI invocation) and for the maintenance of the context between requests (by storing it in an HTTP sessio, for
+example).
 <p>
-A request context is associated with the current execution thread. It holds
-objects that would otherwise need to be included in many method signatures, 
-such as for authentication.</p>
+A security context is associated with the current execution thread for the duration of the request, making the
+authentication information it contains available throughout all the layers of an application.
 </body>
 </html>
 

+ 43 - 0
core/src/test/java/org/springframework/security/context/HttpSessionSecurityContextRepositoryTests.java

@@ -161,6 +161,49 @@ public class HttpSessionSecurityContextRepositoryTests {
         assertTrue(repo.generateNewContext() instanceof MockContext);
     }
 
+    @Test
+    @SuppressWarnings("deprecation")
+    public void sessionDisableUrlRewritingPreventsSessionIdBeingWrittenToUrl() throws Exception {
+        HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
+        MockHttpServletRequest request = new MockHttpServletRequest();
+        final String sessionId = ";jsessionid=id";
+        MockHttpServletResponse response = new MockHttpServletResponse() {
+            @Override
+            public String encodeRedirectUrl(String url) {
+                return url + sessionId;
+            }
+
+            @Override
+            public String encodeRedirectURL(String url) {
+                return url + sessionId;
+            }
+
+            @Override
+            public String encodeUrl(String url) {
+                return url + sessionId;
+            }
+
+            @Override
+            public String encodeURL(String url) {
+                return url + sessionId;
+            }
+        };
+        HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
+        repo.loadContext(holder);
+        String url = "/aUrl";
+        assertEquals(url + sessionId, holder.getResponse().encodeRedirectUrl(url));
+        assertEquals(url + sessionId, holder.getResponse().encodeRedirectURL(url));
+        assertEquals(url + sessionId, holder.getResponse().encodeUrl(url));
+        assertEquals(url + sessionId, holder.getResponse().encodeURL(url));
+        repo.setDisableUrlRewriting(true);
+        holder = new HttpRequestResponseHolder(request, response);
+        repo.loadContext(holder);
+        assertEquals(url, holder.getResponse().encodeRedirectUrl(url));
+        assertEquals(url, holder.getResponse().encodeRedirectURL(url));
+        assertEquals(url, holder.getResponse().encodeUrl(url));
+        assertEquals(url, holder.getResponse().encodeURL(url));
+    }
+
     static class MockContext implements Cloneable, SecurityContext {
         Authentication a;