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
The following commit(s) were added to refs/heads/main by this push:
new be31c133e enh(jakarta-ee): encrypt SAVED_REQUEST_KEY cookie
be31c133e is described below
commit be31c133e61843f14fddd209da4d9c3609bcc9ef
Author: lprimak <[email protected]>
AuthorDate: Wed May 6 17:14:29 2026 -0500
enh(jakarta-ee): encrypt SAVED_REQUEST_KEY cookie
---
.../shiro/mgt/AbstractRememberMeManager.java | 1 -
.../shiro/ee/filters/FormResubmitSupport.java | 52 +++++++++++++++++-----
.../ee/filters/FormResubmitSupportCookies.java | 3 +-
3 files changed, 44 insertions(+), 12 deletions(-)
diff --git
a/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java
b/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java
index 9107cd679..cfe210713 100644
--- a/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java
+++ b/core/src/main/java/org/apache/shiro/mgt/AbstractRememberMeManager.java
@@ -81,7 +81,6 @@ public abstract class AbstractRememberMeManager implements
RememberMeManager {
* Cipher to use for encrypting/decrypting serialized byte arrays for
added security
*/
private CipherService cipherService = new AesCipherService();
- ;
/**
* Cipher encryption key to use with the Cipher when encrypting data
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 6b463c0af..0e4732eff 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
@@ -34,6 +34,7 @@ import static
org.apache.shiro.ee.filters.FormResubmitSupportCookies.getCookieAg
import static
org.apache.shiro.ee.filters.FormResubmitSupportCookies.getSessionCookieName;
import java.net.URISyntaxException;
import java.util.Collections;
+import org.apache.shiro.crypto.CryptoException;
import org.apache.shiro.ee.filters.Forms.FallbackPredicate;
import static
org.apache.shiro.ee.filters.FormResubmitSupportCookies.transformCookieHeader;
import static
org.apache.shiro.ee.listeners.EnvironmentLoaderListener.isFormResubmitDisabled;
@@ -47,6 +48,7 @@ import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
+import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
import static java.util.function.Predicate.not;
@@ -71,6 +73,7 @@ import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import static org.apache.shiro.ee.util.JakartaTransformer.jakartify;
+import org.apache.shiro.lang.codec.Base64;
import org.apache.shiro.mgt.AbstractRememberMeManager;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
@@ -152,7 +155,7 @@ public class FormResubmitSupport {
DefaultSecurityManager dsm =
getSecurityManager(DefaultSecurityManager.class);
if (dsm.getCacheManager() != null) {
var cache = dsm.getCacheManager().getCache(FORM_DATA_CACHE);
- var rememberMeManager = (AbstractRememberMeManager)
dsm.getRememberMeManager();
+ var rememberMeManager = getRememberMeManager();
if (rememberMeManager != null &&
rememberMeManager.getCipherService() != null) {
cache.put(cacheKey, rememberMeManager.getCipherService()
.encrypt(postData.getBytes(StandardCharsets.UTF_8),
@@ -162,7 +165,7 @@ public class FormResubmitSupport {
cache.put(cacheKey, postData);
}
addCookie(response, request.getServletContext(),
SHIRO_FORM_DATA_KEY,
- cacheKey.toString(), getCookieAge(request, dsm));
+ cacheKey.toString(), getCookieAge(request, dsm), true);
} else {
log.warn("Shiro Cache manager is not configured, cannot store
form data");
}
@@ -192,7 +195,7 @@ public class FormResubmitSupport {
if (dsm.getCacheManager() != null) {
var cache = dsm.getCacheManager().getCache(FORM_DATA_CACHE);
var cacheKey = UUID.fromString(savedFormDataKey);
- var rememberMeManager = (AbstractRememberMeManager)
dsm.getRememberMeManager();
+ var rememberMeManager = getRememberMeManager();
if (rememberMeManager != null &&
rememberMeManager.getCipherService() != null) {
var cachedData = Optional.ofNullable((byte[])
cache.get(cacheKey));
savedFormData = cachedData.map(encryptedData ->
@@ -207,17 +210,38 @@ public class FormResubmitSupport {
}
static String decrypt(byte[] encrypted, AbstractRememberMeManager
rememberMeManager) {
- return new String(rememberMeManager.getCipherService()
- .decrypt(encrypted,
rememberMeManager.getDecryptionCipherKey()).getClonedBytes(),
- StandardCharsets.UTF_8);
+ try {
+ Objects.requireNonNull(rememberMeManager, "rememberMeManager
cannot be null.");
+ return new String(rememberMeManager.getCipherService()
+ .decrypt(encrypted,
rememberMeManager.getDecryptionCipherKey()).getClonedBytes(),
+ StandardCharsets.UTF_8);
+ } catch (CryptoException e) {
+ log.debug("Failed to decrypt", e);
+ return null;
+ }
+ }
+
+ static String decrypt(String encrypted, AbstractRememberMeManager
rememberMeManager) {
+ if (encrypted == null) {
+ return null;
+ }
+ try {
+ return decrypt(Base64.decode(encrypted), rememberMeManager);
+ } catch (IllegalArgumentException e) {
+ log.debug("Failed to decode", e);
+ return null;
+ }
}
static void saveRequest(HttpServletRequest request, HttpServletResponse
response, boolean useReferer) {
String path = useReferer ? getReferer(request)
: Servlets.getRequestURLWithQueryString(request);
- if (path != null) {
+ var rememberMeManager = getRememberMeManager();
+ if (path != null && rememberMeManager != null) {
Servlets.addResponseCookie(request, response,
WebUtils.SAVED_REQUEST_KEY,
- path, null, request.getContextPath(),
+
rememberMeManager.getCipherService().encrypt(path.getBytes(StandardCharsets.UTF_8),
+
rememberMeManager.getEncryptionCipherKey()).toBase64(),
+ null, request.getContextPath(),
// cookie age = session timeout
getCookieAge(request, getSecurityManager()));
}
@@ -256,7 +280,7 @@ public class FormResubmitSupport {
@SneakyThrows({IOException.class, InterruptedException.class})
static void redirectToSaved(HttpServletRequest request,
HttpServletResponse response,
FallbackPredicate useFallbackPath, String fallbackPath, boolean
resubmit) {
- String savedRequest = Servlets.getRequestCookie(request,
WebUtils.SAVED_REQUEST_KEY);
+ String savedRequest = decrypt(Servlets.getRequestCookie(request,
WebUtils.SAVED_REQUEST_KEY), getRememberMeManager());
if (savedRequest != null) {
doRedirectToSaved(request, response, savedRequest, resubmit);
} else {
@@ -479,7 +503,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));
+ entry.getKey(), entry.getValue(), -1, false));
if ((response.statusCode() == FOUND || redirect) &&
isPartialAjaxRequest) {
originalResponse.setHeader(CONTENT_TYPE, TEXT_XML);
originalResponse.setCharacterEncoding(StandardCharsets.UTF_8.name());
@@ -544,6 +568,14 @@ public class FormResubmitSupport {
return rv;
}
+ private static AbstractRememberMeManager getRememberMeManager() {
+ if (isSecurityManagerTypeOf(getSecurityManager(),
DefaultSecurityManager.class)) {
+ var dsm = getSecurityManager(DefaultSecurityManager.class);
+ return (AbstractRememberMeManager) dsm.getRememberMeManager();
+ }
+ return null;
+ }
+
private static String getJSFNewViewState(URI savedRequest, HttpClient
client, String savedFormData)
throws IOException, InterruptedException {
var getRequest =
HttpRequest.newBuilder().uri(savedRequest).GET().build();
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 ac3fa41ec..2bc9aeca5 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
@@ -42,10 +42,11 @@ public class FormResubmitSupportCookies {
static final String DONT_ADD_ANY_MORE_COOKIES =
"org.apache.shiro.no-more-cookies";
static void addCookie(@NonNull HttpServletResponse response,
ServletContext servletContext,
- @NonNull String cookieName, @NonNull String cookieValue, int
maxAge) {
+ @NonNull String cookieName, @NonNull String cookieValue, int
maxAge, boolean httpOnly) {
var cookie = new Cookie(cookieName, cookieValue);
cookie.setPath(servletContext.getContextPath());
cookie.setMaxAge(maxAge);
+ cookie.setHttpOnly(httpOnly);
if
(EnvironmentLoaderListener.isFormResubmitSecureCookies(servletContext)) {
cookie.setSecure(true);
}