diff --git a/web/src/main/java/org/springframework/security/web/savedrequest/HttpSessionRequestCache.java b/web/src/main/java/org/springframework/security/web/savedrequest/HttpSessionRequestCache.java index 549a0fcfb4..6b8fec94d3 100644 --- a/web/src/main/java/org/springframework/security/web/savedrequest/HttpSessionRequestCache.java +++ b/web/src/main/java/org/springframework/security/web/savedrequest/HttpSessionRequestCache.java @@ -103,11 +103,11 @@ public class HttpSessionRequestCache implements RequestCache { @Override public HttpServletRequest getMatchingRequest(HttpServletRequest request, HttpServletResponse response) { if (this.matchingRequestParameterName != null) { - if (!StringUtils.hasText(request.getQueryString()) - || !UriComponentsBuilder.fromUriString(UrlUtils.buildRequestUrl(request)) - .build() - .getQueryParams() - .containsKey(this.matchingRequestParameterName)) { + if (!StringUtils.hasText(request.getQueryString()) || !UriComponentsBuilder.newInstance() + .query(request.getQueryString()) + .build() + .getQueryParams() + .containsKey(this.matchingRequestParameterName)) { this.logger.trace( "matchingRequestParameterName is required for getMatchingRequest to lookup a value, but not provided"); return null; diff --git a/web/src/test/java/org/springframework/security/web/savedrequest/HttpSessionRequestCacheTests.java b/web/src/test/java/org/springframework/security/web/savedrequest/HttpSessionRequestCacheTests.java index e19a5f177d..1074b3649c 100644 --- a/web/src/test/java/org/springframework/security/web/savedrequest/HttpSessionRequestCacheTests.java +++ b/web/src/test/java/org/springframework/security/web/savedrequest/HttpSessionRequestCacheTests.java @@ -168,6 +168,21 @@ public class HttpSessionRequestCacheTests { verify(request, never()).getParameterMap(); } + // gh-16656 + @Test + public void getMatchingRequestWhenMatchingRequestPathContainsPercentSignThenLookedUp() { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.setServletPath("/30 % off"); + HttpSessionRequestCache cache = new HttpSessionRequestCache(); + cache.saveRequest(request, new MockHttpServletResponse()); + MockHttpServletRequest requestToMatch = new MockHttpServletRequest(); + requestToMatch.setServletPath("/30 % off"); + requestToMatch.setQueryString("continue"); + requestToMatch.setSession(request.getSession()); + HttpServletRequest matchingRequest = cache.getMatchingRequest(requestToMatch, new MockHttpServletResponse()); + assertThat(matchingRequest).isNotNull(); + } + private static final class CustomSavedRequest implements SavedRequest { private final SavedRequest delegate;