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

This commit is contained in:
Luke Taylor 2008-12-16 17:35:34 +00:00
parent 717fdcfec3
commit b24cc17dea
4 changed files with 113 additions and 13 deletions

View File

@ -61,6 +61,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
private Object contextObject = new SecurityContextImpl(); private Object contextObject = new SecurityContextImpl();
private boolean cloneFromHttpSession = false; private boolean cloneFromHttpSession = false;
private boolean allowSessionCreation = true; private boolean allowSessionCreation = true;
private boolean disableUrlRewriting = false;
private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl(); private AuthenticationTrustResolver authenticationTrustResolver = new AuthenticationTrustResolverImpl();
@ -234,6 +235,16 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
this.allowSessionCreation = allowSessionCreation; 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 ================================================================================================== //~ Inner Classes ==================================================================================================
/** /**
@ -265,7 +276,7 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
SaveToSessionResponseWrapper(HttpServletResponse response, HttpServletRequest request, SaveToSessionResponseWrapper(HttpServletResponse response, HttpServletRequest request,
boolean httpSessionExistedAtStartOfRequest, boolean httpSessionExistedAtStartOfRequest,
int contextHashBeforeChainExecution) { int contextHashBeforeChainExecution) {
super(response); super(response, disableUrlRewriting);
this.request = request; this.request = request;
this.httpSessionExistedAtStartOfRequest = httpSessionExistedAtStartOfRequest; this.httpSessionExistedAtStartOfRequest = httpSessionExistedAtStartOfRequest;
this.contextHashBeforeChainExecution = contextHashBeforeChainExecution; this.contextHashBeforeChainExecution = contextHashBeforeChainExecution;

View File

@ -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 * 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> * 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> * <p>
* Sub-classes should implement the {@link #saveContext(SecurityContext context)} method. * Sub-classes should implement the {@link #saveContext(SecurityContext context)} method.
* <p>
* Support is also provided for disabling URL rewriting
* *
* @author Luke Taylor * @author Luke Taylor
* @author Marten Algesten * @author Marten Algesten
* @version $Id$ * @version $Id$
* @since 2.5 * @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); super(response);
this.disableUrlRewriting = disableUrlRewriting;
} }
/** /**
@ -36,7 +46,8 @@ abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResp
* Makes sure the session is updated before calling the * Makes sure the session is updated before calling the
* superclass <code>sendError()</code> * superclass <code>sendError()</code>
*/ */
public void sendError(int sc) throws IOException { @Override
public final void sendError(int sc) throws IOException {
doSaveContext(); doSaveContext();
super.sendError(sc); super.sendError(sc);
} }
@ -45,7 +56,8 @@ abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResp
* Makes sure the session is updated before calling the * Makes sure the session is updated before calling the
* superclass <code>sendError()</code> * 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(); doSaveContext();
super.sendError(sc, msg); super.sendError(sc, msg);
} }
@ -54,7 +66,8 @@ abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResp
* Makes sure the context is stored before calling the * Makes sure the context is stored before calling the
* superclass <code>sendRedirect()</code> * superclass <code>sendRedirect()</code>
*/ */
public void sendRedirect(String location) throws IOException { @Override
public final void sendRedirect(String location) throws IOException {
doSaveContext(); doSaveContext();
super.sendRedirect(location); super.sendRedirect(location);
} }
@ -67,10 +80,42 @@ abstract class SaveContextOnUpdateOrErrorResponseWrapper extends HttpServletResp
contextSaved = true; 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. * 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; return contextSaved;
} }

View File

@ -1,10 +1,11 @@
<html> <html>
<body> <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> <p>
A request context is associated with the current execution thread. It holds A security context is associated with the current execution thread for the duration of the request, making the
objects that would otherwise need to be included in many method signatures, authentication information it contains available throughout all the layers of an application.
such as for authentication.</p>
</body> </body>
</html> </html>

View File

@ -161,6 +161,49 @@ public class HttpSessionSecurityContextRepositoryTests {
assertTrue(repo.generateNewContext() instanceof MockContext); 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 { static class MockContext implements Cloneable, SecurityContext {
Authentication a; Authentication a;