This is an automated email from the ASF dual-hosted git repository. lprimak pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/shiro.git
commit 4c8b6c481dae3ccc7214282f4b3eae1c61cc23ab Author: lprimak <[email protected]> AuthorDate: Wed Aug 19 20:35:13 2026 -0500 bugfix: improve cookie handling in form resubmission support --- .../apache/shiro/ee/filters/FormResubmitSupport.java | 2 +- .../shiro/ee/filters/FormResubmitSupportCookies.java | 17 +++++++++++++++-- .../org/apache/shiro/ee/filters/FormSupportTest.java | 18 +++++++++++++++--- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupport.java b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupport.java index 7edbb7b20..c3e78686b 100644 --- a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupport.java +++ b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupport.java @@ -573,7 +573,7 @@ public class FormResubmitSupport { .entrySet().stream().filter(not(entry -> entry.getKey() .startsWith(getSessionCookieName(servletContext, getSecurityManager())))) .forEach(entry -> addCookie(originalResponse, servletContext, - entry.getKey(), entry.getValue(), -1, false)); + entry.getKey(), entry.getValue())); if ((response.statusCode() == FOUND || redirect) && isPartialAjaxRequest) { originalResponse.setHeader(CONTENT_TYPE, TEXT_XML); originalResponse.setCharacterEncoding(StandardCharsets.UTF_8.name()); diff --git a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupportCookies.java b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupportCookies.java index a0f7df7b8..d4f381a4a 100644 --- a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupportCookies.java +++ b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/FormResubmitSupportCookies.java @@ -22,6 +22,7 @@ import java.net.URI; import java.time.Duration; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import jakarta.servlet.ServletContext; @@ -59,6 +60,18 @@ public class FormResubmitSupportCookies { response.addCookie(cookie); } + static void addCookie(@NonNull HttpServletResponse response, ServletContext servletContext, + @NonNull String cookieName, @NonNull HttpCookie inputCookie) { + var cookie = new Cookie(cookieName, inputCookie.getValue()); + cookie.setPath(inputCookie.getPath() != null ? inputCookie.getPath() : servletContext.getContextPath()); + cookie.setMaxAge(Math.toIntExact(inputCookie.getMaxAge())); + cookie.setHttpOnly(inputCookie.isHttpOnly()); + if (EnvironmentLoaderListener.isFormResubmitSecureCookies(servletContext)) { + cookie.setSecure(true); + } + response.addCookie(cookie); + } + static void deleteCookie(@NonNull HttpServletResponse response, ServletContext servletContext, @NonNull String cookieName) { var cookieToDelete = new Cookie(cookieName, "tbd"); @@ -94,9 +107,9 @@ public class FormResubmitSupportCookies { } } - static Map<String, String> transformCookieHeader(@NonNull List<String> cookies) { + static Map<String, HttpCookie> transformCookieHeader(@NonNull List<String> cookies) { return cookieStreamFromHeader(cookies) - .collect(Collectors.toMap(HttpCookie::getName, HttpCookie::getValue, (var, v2) -> v2)); + .collect(Collectors.toMap(HttpCookie::getName, Function.identity(), (var, v2) -> v2)); } static Stream<HttpCookie> cookieStreamFromHeader(@NonNull List<String> cookies) { diff --git a/support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/FormSupportTest.java b/support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/FormSupportTest.java index 4ff4cfc5a..36ab39bf5 100644 --- a/support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/FormSupportTest.java +++ b/support/jakarta-ee/src/test/java/org/apache/shiro/ee/filters/FormSupportTest.java @@ -23,11 +23,13 @@ import static org.apache.shiro.ee.filters.FormResubmitSupport.isJSFStatefulForm; import static org.apache.shiro.ee.filters.FormResubmitSupport.noJSFAjaxRequests; import static org.apache.shiro.ee.filters.FormResubmitSupportCookies.transformCookieHeader; +import java.net.HttpCookie; import java.net.URLDecoder; import java.time.Duration; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import jakarta.servlet.http.HttpServletRequest; import static org.assertj.core.api.Assertions.assertThat; @@ -327,11 +329,21 @@ class FormSupportTest { @Test void parseCookies() { - var map = Map.of("name1", "value1", "name2", "value2", "name3", "value3"); + var map = Map.of("name1", "value1", "name2", "value2", "name3", "value3") + .entrySet().stream() + .collect(Collectors.toUnmodifiableMap(Map.Entry::getKey, + entry -> { + var cookie = new HttpCookie(entry.getKey(), entry.getValue()); + if (entry.getKey().equals("name2")) { + cookie.setPath("/my/path"); + } + return cookie; + })); + assertThat(transformCookieHeader(List.of("name1=value1", "name2=value2; path=/my/path", "name3=value3"))).isEqualTo(map); - assertThat(transformCookieHeader(List.of("name="))).isEqualTo(Map.of("name", "")); + assertThat(transformCookieHeader(List.of("name="))).isEqualTo(Map.of("name", new HttpCookie("name", ""))); assertThat(transformCookieHeader(List.of("JSESSIONID=\"abc\"; $Version=\"1\"; $Path=\"/mypath\""))) - .isEqualTo(Map.of("JSESSIONID", "abc")); + .isEqualTo(Map.of("JSESSIONID", new HttpCookie("JSESSIONID", "abc"))); } @Test
