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 9e51943f72..e1c8a205cb 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 @@ -16,6 +16,7 @@ package org.springframework.security.web.savedrequest; +import jakarta.servlet.DispatcherType; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpSession; @@ -38,6 +39,7 @@ * * @author Luke Taylor * @author Eddú Meléndez + * @author Andrey Litvitski * @since 3.0 */ public class HttpSessionRequestCache implements RequestCache { @@ -61,6 +63,17 @@ public class HttpSessionRequestCache implements RequestCache { */ @Override public void saveRequest(HttpServletRequest request, HttpServletResponse response) { + boolean documentRequest = "document".equals(request.getHeader("Sec-Fetch-Dest")); + boolean dispatchError = DispatcherType.ERROR.equals(request.getDispatcherType()); + + if (!documentRequest && dispatchError) { + if (this.logger.isTraceEnabled()) { + this.logger + .trace("Did not save request because it is an ERROR dispatcher and not a primary document request"); + } + return; + } + if (!this.requestMatcher.matches(request)) { if (this.logger.isTraceEnabled()) { this.logger 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 dc05a00562..7ad824810f 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 @@ -21,6 +21,7 @@ import java.util.Locale; import java.util.Map; +import jakarta.servlet.DispatcherType; import jakarta.servlet.http.Cookie; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -40,6 +41,7 @@ /** * @author Luke Taylor * @author Eddú Meléndez + * @author Andrey Litvitski * @since 3.0 */ public class HttpSessionRequestCacheTests { @@ -168,6 +170,18 @@ public void getMatchingRequestWhenMatchingRequestParameterNameSetThenDoesNotInvo verify(request, never()).getParameterMap(); } + // gh-17686 + @Test + public void saveRequestShouldNotSaveRequestWhenErrorDispatcherAndNonDocumentRequest() { + HttpSessionRequestCache cache = new HttpSessionRequestCache(); + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/destination"); + request.setDispatcherType(DispatcherType.ERROR); + request.addHeader("Sec-Fetch-Dest", "image"); + MockHttpServletResponse response = new MockHttpServletResponse(); + cache.saveRequest(request, response); + assertThat(request.getSession().getAttribute(HttpSessionRequestCache.SAVED_REQUEST)).isNull(); + } + private static final class CustomSavedRequest implements SavedRequest { private final SavedRequest delegate;