SEC-1167: Extended SavedRequest interface to allow it to be used by wrapper. Removed null checks in wrapper, as the SavedRequest cannot now be null.

This commit is contained in:
Luke Taylor 2009-09-13 16:27:35 +00:00
parent 4064b7b4f6
commit 9c7423599e
5 changed files with 76 additions and 165 deletions

View File

@ -15,23 +15,24 @@
package org.springframework.security.web.savedrequest;
import org.springframework.security.web.PortResolver;
import org.springframework.security.web.util.UrlUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.web.PortResolver;
import org.springframework.security.web.util.UrlUtils;
import org.springframework.util.Assert;
/**
* Represents central information from a <code>HttpServletRequest</code>.<p>This class is used by {@link
@ -237,22 +238,22 @@ public class DefaultSavedRequest implements SavedRequest {
pathInfo, queryString);
}
public Iterator<String> getHeaderNames() {
return (headers.keySet().iterator());
public Collection<String> getHeaderNames() {
return headers.keySet();
}
public Iterator<String> getHeaderValues(String name) {
public List<String> getHeaderValues(String name) {
List<String> values = headers.get(name);
if (values == null) {
values = Collections.emptyList();
return Collections.emptyList();
}
return (values.iterator());
return values;
}
public Iterator<Locale> getLocales() {
return (locales.iterator());
public List<Locale> getLocales() {
return locales;
}
public String getMethod() {
@ -263,8 +264,8 @@ public class DefaultSavedRequest implements SavedRequest {
return parameters;
}
public Iterator<String> getParameterNames() {
return (parameters.keySet().iterator());
public Collection<String> getParameterNames() {
return parameters.keySet();
}
public String[] getParameterValues(String name) {

View File

@ -1,8 +1,16 @@
package org.springframework.security.web.savedrequest;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.Cookie;
/**
* Encapsulates the functionality required of a cached request, in order for an authentication mechanism (typically
* form-based login) to redirect to the original URL.
* Encapsulates the functionality required of a cached request for both an authentication mechanism (typically
* form-based login) to redirect to the original URL and for a <tt>RequestCache</tt> to build a wrapped request,
* reproducing the original request data.
*
* @author Luke Taylor
* @version $Id$
@ -14,4 +22,18 @@ public interface SavedRequest extends java.io.Serializable {
* @return the URL for the saved request, allowing a redirect to be performed.
*/
String getRedirectUrl();
List<Cookie> getCookies();
String getMethod();
List<String> getHeaderValues(String name);
Collection<String> getHeaderNames();
List<Locale> getLocales();
String[] getParameterValues(String name);
Map<String,String[]> getParameterMap();
}

View File

@ -21,7 +21,6 @@ import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@ -45,9 +44,6 @@ import org.apache.commons.logging.LogFactory;
*
* <p>
* Added into a request by {@link org.springframework.security.web.savedrequest.RequestCacheAwareFilter}.
* </p>
*
* TODO: savedRequest cannot now be null, so convert the tests to reflect this and remove the null checks.
*
* @author Andrey Grebnev
* @author Ben Alex
@ -65,7 +61,7 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
//~ Instance fields ================================================================================================
protected DefaultSavedRequest savedRequest = null;
protected SavedRequest savedRequest = null;
/**
* The set of SimpleDateFormat formats to use in getDateHeader(). Notice that because SimpleDateFormat is
@ -75,7 +71,7 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
//~ Constructors ===================================================================================================
public SavedRequestAwareWrapper(DefaultSavedRequest saved, HttpServletRequest request) {
public SavedRequestAwareWrapper(SavedRequest saved, HttpServletRequest request) {
super(request);
savedRequest = saved;
@ -92,9 +88,6 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
@Override
public Cookie[] getCookies() {
if (savedRequest == null) {
return super.getCookies();
}
List<Cookie> cookies = savedRequest.getCookies();
return cookies.toArray(new Cookie[cookies.size()]);
@ -102,9 +95,6 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
@Override
public long getDateHeader(String name) {
if (savedRequest == null) {
return super.getDateHeader(name);
}
String value = getHeader(name);
if (value == null) {
@ -123,128 +113,79 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
@Override
public String getHeader(String name) {
if (savedRequest == null) {
return super.getHeader(name);
}
List<String> values = savedRequest.getHeaderValues(name);
String header = null;
Iterator<String> iterator = savedRequest.getHeaderValues(name);
while (iterator.hasNext()) {
header = iterator.next();
break;
}
return header;
return values.isEmpty() ? null : values.get(0);
}
@Override
@SuppressWarnings("unchecked")
public Enumeration getHeaderNames() {
if (savedRequest == null) {
return super.getHeaderNames();
}
return new Enumerator<String>(savedRequest.getHeaderNames());
}
@Override
@SuppressWarnings("unchecked")
public Enumeration getHeaders(String name) {
if (savedRequest == null) {
return super.getHeaders(name);
} else {
return new Enumerator<String>(savedRequest.getHeaderValues(name));
}
return new Enumerator<String>(savedRequest.getHeaderValues(name));
}
@Override
public int getIntHeader(String name) {
if (savedRequest == null) {
return super.getIntHeader(name);
} else {
String value = getHeader(name);
String value = getHeader(name);
if (value == null) {
return -1;
} else {
return Integer.parseInt(value);
}
if (value == null) {
return -1;
} else {
return Integer.parseInt(value);
}
}
@Override
public Locale getLocale() {
if (savedRequest == null) {
return super.getLocale();
} else {
Locale locale = null;
Iterator<Locale> iterator = savedRequest.getLocales();
List<Locale> locales = savedRequest.getLocales();
while (iterator.hasNext()) {
locale = (Locale) iterator.next();
break;
}
if (locale == null) {
return defaultLocale;
} else {
return locale;
}
}
return locales.isEmpty() ? Locale.getDefault() : locales.get(0);
}
@Override
@SuppressWarnings("unchecked")
public Enumeration getLocales() {
if (savedRequest == null) {
return super.getLocales();
List<Locale> locales = savedRequest.getLocales();
if (locales.isEmpty()) {
// Fall back to default locale
locales = new ArrayList<Locale>(1);
locales.add(Locale.getDefault());
}
Iterator<Locale> iterator = savedRequest.getLocales();
if (iterator.hasNext()) {
return new Enumerator<Locale>(iterator);
}
// Fall back to default locale
ArrayList<Locale> results = new ArrayList<Locale>(1);
results.add(defaultLocale);
return new Enumerator<Locale>(results.iterator());
return new Enumerator<Locale>(locales);
}
@Override
public String getMethod() {
if (savedRequest == null) {
return super.getMethod();
} else {
return savedRequest.getMethod();
}
return savedRequest.getMethod();
}
/**
* If the parameter is available from the wrapped request then either
* <ol>
* <li>There is no saved request (it a normal request)</li>
* <li>There is a saved request, but the request has been forwarded/included to a URL with parameters, either
* supplementing or overriding the saved request values.</li>
* </ol>
* In both cases the value from the wrapped request should be used.
* If the parameter is available from the wrapped request then the request has been forwarded/included to a URL
* with parameters, either supplementing or overriding the saved request values.
* <p>
* In this case, the value from the wrapped request should be used.
* <p>
* If the value from the wrapped request is null, an attempt will be made to retrieve the parameter
* from the DefaultSavedRequest, if available..
* from the saved request.
*/
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value != null || savedRequest == null) {
if (value != null) {
return value;
}
String[] values = savedRequest.getParameterValues(name);
if (values == null || values.length == 0) {
return null;
}
@ -255,10 +196,6 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
@Override
@SuppressWarnings("unchecked")
public Map getParameterMap() {
if (savedRequest == null) {
return super.getParameterMap();
}
Set<String> names = getCombinedParameterNames();
Map<String, String[]> parameterMap = new HashMap<String, String[]>(names.size());
@ -273,10 +210,7 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
private Set<String> getCombinedParameterNames() {
Set<String> names = new HashSet<String>();
names.addAll(super.getParameterMap().keySet());
if (savedRequest != null) {
names.addAll(savedRequest.getParameterMap().keySet());
}
names.addAll(savedRequest.getParameterMap().keySet());
return names;
}
@ -289,10 +223,6 @@ class SavedRequestAwareWrapper extends HttpServletRequestWrapper {
@Override
public String[] getParameterValues(String name) {
if (savedRequest == null) {
return super.getParameterValues(name);
}
String[] savedRequestParams = savedRequest.getParameterValues(name);
String[] wrappedRequestParams = super.getParameterValues(name);

View File

@ -10,14 +10,14 @@ import org.springframework.mock.web.MockHttpServletRequest;
/**
*
*/
public class SavedRequestTests {
public class DefaultSavedRequestTests {
@Test
public void headersAreCaseInsensitive() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("USER-aGenT", "Mozilla");
DefaultSavedRequest saved = new DefaultSavedRequest(request, new MockPortResolver(8080, 8443));
assertEquals("Mozilla", saved.getHeaderValues("user-agent").next());
assertEquals("Mozilla", saved.getHeaderValues("user-agent").get(0));
}
// TODO: Why are parameters case insensitive. I think this is a mistake

View File

@ -19,19 +19,10 @@ import org.springframework.security.web.savedrequest.SavedRequestAwareWrapper;
public class SavedRequestAwareWrapperTests {
private SavedRequestAwareWrapper createWrapper(MockHttpServletRequest requestToSave, MockHttpServletRequest requestToWrap) {
DefaultSavedRequest saved = requestToSave == null ? null : new DefaultSavedRequest(requestToSave, new PortResolverImpl());
DefaultSavedRequest saved = new DefaultSavedRequest(requestToSave, new PortResolverImpl());
return new SavedRequestAwareWrapper(saved, requestToWrap);
}
@Test
public void wrappedRequestCookiesAreReturnedIfNoSavedRequestIsSet() throws Exception {
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
wrappedRequest.setCookies(new Cookie[] {new Cookie("cookie", "fromwrapped")});
SavedRequestAwareWrapper wrapper = createWrapper(null, wrappedRequest);
assertEquals(1, wrapper.getCookies().length);
assertEquals("fromwrapped", wrapper.getCookies()[0].getValue());
}
@Test
public void savedRequestCookiesAreReturnedIfSavedRequestIsSet() throws Exception {
MockHttpServletRequest savedRequest = new MockHttpServletRequest();
@ -61,27 +52,6 @@ public class SavedRequestAwareWrapperTests {
assertEquals("header", wrapper.getHeaderNames().nextElement());
}
@Test
@SuppressWarnings("unchecked")
public void wrappedRequestHeaderIsReturnedIfSavedRequestIsNotSet() throws Exception {
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
wrappedRequest.addHeader("header", "wrappedheader");
SavedRequestAwareWrapper wrapper = createWrapper(null, wrappedRequest);
assertNull(wrapper.getHeader("nonexistent"));
Enumeration headers = wrapper.getHeaders("nonexistent");
assertFalse(headers.hasMoreElements());
assertEquals("wrappedheader", wrapper.getHeader("header"));
headers = wrapper.getHeaders("header");
assertTrue(headers.hasMoreElements());
assertEquals("wrappedheader", headers.nextElement());
assertFalse(headers.hasMoreElements());
assertTrue(wrapper.getHeaderNames().hasMoreElements());
assertEquals("header", wrapper.getHeaderNames().nextElement());
}
@Test
/* SEC-830. Assume we have a request to /someUrl?action=foo (the saved request)
* and then RequestDispatcher.forward() it to /someUrl?action=bar.
@ -125,8 +95,7 @@ public class SavedRequestAwareWrapperTests {
@Test
public void getParameterValuesReturnsNullIfParameterIsntSet() {
MockHttpServletRequest wrappedRequest = new MockHttpServletRequest();
SavedRequestAwareWrapper wrapper = new SavedRequestAwareWrapper(null, wrappedRequest);
SavedRequestAwareWrapper wrapper = createWrapper(new MockHttpServletRequest(), new MockHttpServletRequest());
assertNull(wrapper.getParameterValues("action"));
assertNull(wrapper.getParameterMap().get("action"));
}
@ -148,7 +117,7 @@ public class SavedRequestAwareWrapperTests {
}
@Test
public void expecteDateHeaderIsReturnedFromSavedAndWrappedRequests() throws Exception {
public void expecteDateHeaderIsReturnedFromSavedRequest() throws Exception {
SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
String nowString = FastHttpDateFormat.getCurrentDate();
Date now = formatter.parse(nowString);
@ -158,12 +127,6 @@ public class SavedRequestAwareWrapperTests {
assertEquals(now.getTime(), wrapper.getDateHeader("header"));
assertEquals(-1L, wrapper.getDateHeader("nonexistent"));
// Now try with no saved request
request = new MockHttpServletRequest();
request.addHeader("header", now);
wrapper = createWrapper(null, request);
assertEquals(now.getTime(), wrapper.getDateHeader("header"));
}
@Test(expected=IllegalArgumentException.class)
@ -179,8 +142,6 @@ public class SavedRequestAwareWrapperTests {
MockHttpServletRequest request = new MockHttpServletRequest("PUT", "/notused");
SavedRequestAwareWrapper wrapper = createWrapper(request, new MockHttpServletRequest("GET", "/notused"));
assertEquals("PUT", wrapper.getMethod());
wrapper = createWrapper(null, request);
assertEquals("PUT", wrapper.getMethod());
}
@Test
@ -192,9 +153,6 @@ public class SavedRequestAwareWrapperTests {
assertEquals(999, wrapper.getIntHeader("header"));
assertEquals(-1, wrapper.getIntHeader("nonexistent"));
wrapper = createWrapper(null, request);
assertEquals(999, wrapper.getIntHeader("header"));
}
}