Skip to content

Commit bd819e4

Browse files
committed
Improve request matching logic, repair request cache deleted by mistake.
Fix RequestCache throw exception and error redirect. Fix and improve CookieRequestCache unit tests. Add notMatchingRequestWhenRequestNotContainsSavedRequestCookie unit test.
1 parent f8f3302 commit bd819e4

File tree

2 files changed

+60
-10
lines changed

2 files changed

+60
-10
lines changed

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

+40-8
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import org.springframework.security.web.util.matcher.AnyRequestMatcher;
2222
import org.springframework.security.web.util.matcher.RequestMatcher;
2323
import org.springframework.util.Assert;
24+
import org.springframework.util.MultiValueMap;
25+
import org.springframework.util.StringUtils;
2426
import org.springframework.web.util.UriComponents;
2527
import org.springframework.web.util.UriComponentsBuilder;
2628
import org.springframework.web.util.WebUtils;
@@ -29,6 +31,7 @@
2931
import javax.servlet.http.HttpServletRequest;
3032
import javax.servlet.http.HttpServletResponse;
3133
import java.util.Base64;
34+
import java.util.HashMap;
3235

3336

3437
/**
@@ -52,7 +55,7 @@ public void saveRequest(HttpServletRequest request, HttpServletResponse response
5255
Cookie savedCookie = new Cookie(COOKIE_NAME, encodeCookie(redirectUrl));
5356
savedCookie.setMaxAge(COOKIE_MAX_AGE);
5457
savedCookie.setSecure(request.isSecure());
55-
savedCookie.setPath(request.getContextPath());
58+
savedCookie.setPath(getCookiePath(request));
5659
savedCookie.setHttpOnly(true);
5760

5861
response.addCookie(savedCookie);
@@ -65,7 +68,7 @@ public void saveRequest(HttpServletRequest request, HttpServletResponse response
6568
public SavedRequest getRequest(HttpServletRequest request, HttpServletResponse response) {
6669
Cookie savedRequestCookie = WebUtils.getCookie(request, COOKIE_NAME);
6770
if (savedRequestCookie != null) {
68-
String originalURI = decodeCookie(savedRequestCookie.getValue());
71+
final String originalURI = decodeCookie(savedRequestCookie.getValue());
6972
UriComponents uriComponents = UriComponentsBuilder.fromUriString(originalURI).build();
7073
DefaultSavedRequest.Builder builder = new DefaultSavedRequest.Builder();
7174

@@ -77,32 +80,44 @@ public SavedRequest getRequest(HttpServletRequest request, HttpServletResponse r
7780
port = 80;
7881
}
7982
}
83+
84+
final MultiValueMap<String, String> queryParams = uriComponents.getQueryParams();
85+
86+
if (!queryParams.isEmpty()) {
87+
final HashMap<String, String[]> parameters = new HashMap<>(queryParams.size());
88+
queryParams.forEach((key, value) -> parameters.put(key, value.toArray(new String[]{})));
89+
builder.setParameters(parameters);
90+
}
91+
8092
return builder.setScheme(uriComponents.getScheme())
8193
.setServerName(uriComponents.getHost())
8294
.setRequestURI(uriComponents.getPath())
8395
.setQueryString(uriComponents.getQuery())
8496
.setServerPort(port)
97+
.setMethod(request.getMethod())
8598
.build();
8699
}
87100
return null;
88101
}
89102

90103
@Override
91104
public HttpServletRequest getMatchingRequest(HttpServletRequest request, HttpServletResponse response) {
92-
SavedRequest savedRequest = getRequest(request, response);
93-
if (savedRequest != null) {
94-
removeRequest(request, response);
95-
return new SavedRequestAwareWrapper(savedRequest, request);
105+
SavedRequest saved = this.getRequest(request, response);
106+
if (!this.matchesSavedRequest(request, saved)) {
107+
this.logger.debug("saved request doesn't match");
108+
return null;
109+
} else {
110+
this.removeRequest(request, response);
111+
return new SavedRequestAwareWrapper(saved, request);
96112
}
97-
return null;
98113
}
99114

100115
@Override
101116
public void removeRequest(HttpServletRequest request, HttpServletResponse response) {
102117
Cookie removeSavedRequestCookie = new Cookie(COOKIE_NAME, "");
103118
removeSavedRequestCookie.setSecure(request.isSecure());
104119
removeSavedRequestCookie.setHttpOnly(true);
105-
removeSavedRequestCookie.setPath(request.getContextPath());
120+
removeSavedRequestCookie.setPath(getCookiePath(request));
106121
removeSavedRequestCookie.setMaxAge(0);
107122
response.addCookie(removeSavedRequestCookie);
108123
}
@@ -115,6 +130,23 @@ private static String decodeCookie(String encodedCookieValue) {
115130
return new String(Base64.getDecoder().decode(encodedCookieValue.getBytes()));
116131
}
117132

133+
private static String getCookiePath(HttpServletRequest request) {
134+
final String contextPath = request.getContextPath();
135+
if (StringUtils.isEmpty(contextPath)) {
136+
return "/";
137+
}
138+
return contextPath;
139+
}
140+
141+
private boolean matchesSavedRequest(HttpServletRequest request, SavedRequest savedRequest) {
142+
if (savedRequest == null) {
143+
return false;
144+
} else {
145+
String currentUrl = UrlUtils.buildFullRequestUrl(request);
146+
return savedRequest.getRedirectUrl().equals(currentUrl);
147+
}
148+
}
149+
118150
/**
119151
* Allows selective use of saved requests for a subset of requests. By default any
120152
* request will be cached by the {@code saveRequest} method.

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

+20-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.junit.Test;
1919
import org.springframework.mock.web.MockHttpServletRequest;
2020
import org.springframework.mock.web.MockHttpServletResponse;
21+
import org.springframework.util.StringUtils;
2122

2223
import javax.servlet.http.Cookie;
2324
import javax.servlet.http.HttpServletRequest;
@@ -50,7 +51,7 @@ public void saveRequestWhenMatchesThenSavedRequestInACookieOnResponse() {
5051
assertThat(redirectUrl).isEqualTo("https://abc.com/destination?param1=a&param2=b&param3=1122");
5152

5253
assertThat(savedCookie.getMaxAge()).isEqualTo(-1);
53-
assertThat(savedCookie.getPath()).isEqualTo(request.getContextPath());
54+
assertThat(savedCookie.getPath()).isEqualTo(StringUtils.isEmpty(request.getContextPath()) ? "/" : request.getContextPath());
5455
assertThat(savedCookie.isHttpOnly()).isTrue();
5556
assertThat(savedCookie.getSecure()).isTrue();
5657

@@ -123,7 +124,8 @@ public void matchingRequestWhenRequestDoesNotContainSavedRequestCookieThenReturn
123124
@Test
124125
public void matchingRequestWhenRequestContainsSavedRequestCookieThenSetsAnExpiredCookieInResponse() {
125126
CookieRequestCache cookieRequestCache = new CookieRequestCache();
126-
MockHttpServletRequest request = new MockHttpServletRequest();
127+
MockHttpServletRequest request = requestToSave();
128+
127129
String redirectUrl = "https://abc.com/destination?param1=a&param2=b&param3=1122";
128130
request.setCookies(new Cookie(DEFAULT_COOKIE_NAME, encodeCookie(redirectUrl)));
129131
MockHttpServletResponse response = new MockHttpServletResponse();
@@ -135,6 +137,22 @@ public void matchingRequestWhenRequestContainsSavedRequestCookieThenSetsAnExpire
135137
assertThat(expiredCookie.getMaxAge()).isZero();
136138
}
137139

140+
@Test
141+
public void notMatchingRequestWhenRequestNotContainsSavedRequestCookie() {
142+
CookieRequestCache cookieRequestCache = new CookieRequestCache();
143+
MockHttpServletRequest request = requestToSave();
144+
145+
String redirectUrl = "https://abc.com/api";
146+
request.setCookies(new Cookie(DEFAULT_COOKIE_NAME, encodeCookie(redirectUrl)));
147+
MockHttpServletResponse response = new MockHttpServletResponse();
148+
149+
final HttpServletRequest matchingRequest = cookieRequestCache.getMatchingRequest(request, response);
150+
assertThat(matchingRequest).isNull();
151+
Cookie expiredCookie = response.getCookie(DEFAULT_COOKIE_NAME);
152+
assertThat(expiredCookie).isNull();
153+
154+
}
155+
138156
@Test
139157
public void removeRequestWhenInvokedThenSetsAnExpiredCookieOnResponse() {
140158
CookieRequestCache cookieRequestCache = new CookieRequestCache();

0 commit comments

Comments
 (0)