diff --git a/core/src/main/java/org/springframework/security/context/HttpSessionSecurityContextRepository.java b/core/src/main/java/org/springframework/security/context/HttpSessionSecurityContextRepository.java
index 2551f7fe69..b9569a975f 100644
--- a/core/src/main/java/org/springframework/security/context/HttpSessionSecurityContextRepository.java
+++ b/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 true to disable URL encoding methods in the response wrapper
+ * and prevent the use of jsessionid 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;
diff --git a/core/src/main/java/org/springframework/security/context/SaveContextOnUpdateOrErrorResponseWrapper.java b/core/src/main/java/org/springframework/security/context/SaveContextOnUpdateOrErrorResponseWrapper.java
index 1250ca281b..5d260bc9a8 100644
--- a/core/src/main/java/org/springframework/security/context/SaveContextOnUpdateOrErrorResponseWrapper.java
+++ b/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 SecurityContext
when a sendError()
or sendRedirect
- * happens. See SEC-398.
+ * happens. See issue SEC-398.
*
* Sub-classes should implement the {@link #saveContext(SecurityContext context)} method. + *
+ * 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 sendError()
*/
- 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 sendError()
*/
- 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 sendRedirect()
*/
- 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 saveContext()
because of an error or redirect.
*/
- public boolean isContextSaved() {
+ public final boolean isContextSaved() {
return contextSaved;
}
diff --git a/core/src/main/java/org/springframework/security/context/package.html b/core/src/main/java/org/springframework/security/context/package.html
index 3954b286d4..6684b8943b 100644
--- a/core/src/main/java/org/springframework/security/context/package.html
+++ b/core/src/main/java/org/springframework/security/context/package.html
@@ -1,10 +1,11 @@
-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.
+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. diff --git a/core/src/test/java/org/springframework/security/context/HttpSessionSecurityContextRepositoryTests.java b/core/src/test/java/org/springframework/security/context/HttpSessionSecurityContextRepositoryTests.java index ee5769d3ab..22e40acadd 100644 --- a/core/src/test/java/org/springframework/security/context/HttpSessionSecurityContextRepositoryTests.java +++ b/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;