Skip to content

Commit 18e8836

Browse files
Resolve The matchingRequestParameterName From The Query String
Prior to this commit, the ServletRequest#getParameter method was used in order to verify if the matchingRequestParameterName was present in the request. That method has some side effects like interfering in the execution of the ServletRequest#getInputStream and ServletRequest#getReader method when the request is an HTTP POST (if those methods are invoked after getParameter, or vice-versa, the content won't be available). This commit makes that we only use the query string to check for the parameter, avoiding draining the request's input stream. Closes gh-13731
1 parent aeafcc1 commit 18e8836

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

web/src/main/java/org/springframework/security/web/savedrequest/HttpSessionRequestCache.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
import org.springframework.security.web.util.UrlUtils;
2929
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
3030
import org.springframework.security.web.util.matcher.RequestMatcher;
31+
import org.springframework.util.StringUtils;
32+
import org.springframework.web.util.UriComponentsBuilder;
3133

3234
/**
3335
* {@code RequestCache} which stores the {@code SavedRequest} in the HttpSession.
@@ -100,11 +102,14 @@ public void removeRequest(HttpServletRequest currentRequest, HttpServletResponse
100102

101103
@Override
102104
public HttpServletRequest getMatchingRequest(HttpServletRequest request, HttpServletResponse response) {
103-
if (this.matchingRequestParameterName != null
104-
&& request.getParameter(this.matchingRequestParameterName) == null) {
105-
this.logger.trace(
106-
"matchingRequestParameterName is required for getMatchingRequest to lookup a value, but not provided");
107-
return null;
105+
if (this.matchingRequestParameterName != null) {
106+
if (!StringUtils.hasText(request.getQueryString())
107+
|| !UriComponentsBuilder.fromUriString(UrlUtils.buildRequestUrl(request)).build().getQueryParams()
108+
.containsKey(this.matchingRequestParameterName)) {
109+
this.logger.trace(
110+
"matchingRequestParameterName is required for getMatchingRequest to lookup a value, but not provided");
111+
return null;
112+
}
108113
}
109114
SavedRequest saved = getRequest(request, response);
110115
if (saved == null) {

web/src/test/java/org/springframework/security/web/savedrequest/HttpSessionRequestCacheTests.java

+19-5
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@
3232

3333
import static org.assertj.core.api.Assertions.assertThat;
3434
import static org.mockito.ArgumentMatchers.anyBoolean;
35-
import static org.mockito.Mockito.mock;
35+
import static org.mockito.ArgumentMatchers.anyString;
3636
import static org.mockito.Mockito.never;
37+
import static org.mockito.Mockito.spy;
3738
import static org.mockito.Mockito.verify;
3839

3940
/**
@@ -100,7 +101,7 @@ public void testCustomSessionAttrName() {
100101
public void getMatchingRequestWhenMatchingRequestParameterNameSetThenSessionNotAccessed() {
101102
HttpSessionRequestCache cache = new HttpSessionRequestCache();
102103
cache.setMatchingRequestParameterName("success");
103-
HttpServletRequest request = mock(HttpServletRequest.class);
104+
HttpServletRequest request = spy(new MockHttpServletRequest());
104105
HttpServletRequest matchingRequest = cache.getMatchingRequest(request, new MockHttpServletResponse());
105106
assertThat(matchingRequest).isNull();
106107
verify(request, never()).getSession();
@@ -115,7 +116,6 @@ public void getMatchingRequestWhenMatchingRequestParameterNameSetAndParameterExi
115116
cache.saveRequest(request, new MockHttpServletResponse());
116117
MockHttpServletRequest requestToMatch = new MockHttpServletRequest();
117118
requestToMatch.setQueryString("success"); // gh-12665
118-
requestToMatch.setParameter("success", "");
119119
requestToMatch.setSession(request.getSession());
120120
HttpServletRequest matchingRequest = cache.getMatchingRequest(requestToMatch, new MockHttpServletResponse());
121121
assertThat(matchingRequest).isNotNull();
@@ -131,7 +131,6 @@ public void getMatchingRequestWhenMatchingRequestParameterNameSetAndParameterExi
131131
cache.saveRequest(request, new MockHttpServletResponse());
132132
MockHttpServletRequest requestToMatch = new MockHttpServletRequest();
133133
requestToMatch.setQueryString("param=true&success");
134-
requestToMatch.setParameter("success", "");
135134
requestToMatch.setSession(request.getSession());
136135
HttpServletRequest matchingRequest = cache.getMatchingRequest(requestToMatch, new MockHttpServletResponse());
137136
assertThat(matchingRequest).isNotNull();
@@ -146,13 +145,28 @@ public void getMatchingRequestWhenMatchesThenRemoved() {
146145
assertThat(request.getSession().getAttribute(HttpSessionRequestCache.SAVED_REQUEST)).isNotNull();
147146
MockHttpServletRequest requestToMatch = new MockHttpServletRequest();
148147
requestToMatch.setQueryString("success");
149-
requestToMatch.setParameter("success", "");
150148
requestToMatch.setSession(request.getSession());
151149
HttpServletRequest matchingRequest = cache.getMatchingRequest(requestToMatch, new MockHttpServletResponse());
152150
assertThat(matchingRequest).isNotNull();
153151
assertThat(request.getSession().getAttribute(HttpSessionRequestCache.SAVED_REQUEST)).isNull();
154152
}
155153

154+
// gh-13731
155+
@Test
156+
public void getMatchingRequestWhenMatchingRequestParameterNameSetThenDoesNotInvokeGetParameterMethods() {
157+
HttpSessionRequestCache cache = new HttpSessionRequestCache();
158+
cache.setMatchingRequestParameterName("success");
159+
MockHttpServletRequest mockRequest = new MockHttpServletRequest();
160+
mockRequest.setQueryString("success");
161+
HttpServletRequest request = spy(mockRequest);
162+
HttpServletRequest matchingRequest = cache.getMatchingRequest(request, new MockHttpServletResponse());
163+
assertThat(matchingRequest).isNull();
164+
verify(request, never()).getParameter(anyString());
165+
verify(request, never()).getParameterValues(anyString());
166+
verify(request, never()).getParameterNames();
167+
verify(request, never()).getParameterMap();
168+
}
169+
156170
private static final class CustomSavedRequest implements SavedRequest {
157171

158172
private final SavedRequest delegate;

0 commit comments

Comments
 (0)