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 be89663a1 enh: rememberMe cookie options
be89663a1 is described below
commit be89663a1fd69c3b213c835f1ee7991a1450510d
Author: lprimak <[email protected]>
AuthorDate: Thu Apr 30 10:45:30 2026 -0500
enh: rememberMe cookie options
---
.../shiro/ee/filters/FormResubmitSupport.java | 9 +-----
.../org/apache/shiro/ee/filters/SslFilter.java | 2 +-
.../ee/listeners/EnvironmentLoaderListener.java | 19 +++++++++++--
.../apache/shiro/ee/listeners/IniEnvironment.java | 9 ++++++
.../web/config/AbstractShiroWebConfiguration.java | 4 +--
.../shiro/web/mgt/CookieRememberMeManager.java | 32 ++++++++++++++++++++++
6 files changed, 62 insertions(+), 13 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 95447f342..6b463c0af 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
@@ -50,6 +50,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.UUID;
import static java.util.function.Predicate.not;
+import static org.apache.shiro.ee.listeners.IniEnvironment.hasFacesContext;
import static
org.apache.shiro.web.mgt.CookieRememberMeManager.DEFAULT_REMEMBER_ME_COOKIE_NAME;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@@ -354,14 +355,6 @@ public class FormResubmitSupport {
}
}
- static boolean hasFacesContext() {
- try {
- return Faces.hasContext();
- } catch (Throwable e) {
- return false;
- }
- }
-
static boolean isLoginUrl(HttpServletRequest request) {
String loginUrl = (String) request.getAttribute(LOGIN_URL_ATTR_NAME);
return loginUrl != null &&
request.getRequestURI().equals(request.getContextPath() + loginUrl);
diff --git
a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/SslFilter.java
b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/SslFilter.java
index 9a9a4dcbb..377291fc9 100644
---
a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/SslFilter.java
+++
b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/filters/SslFilter.java
@@ -13,7 +13,7 @@
*/
package org.apache.shiro.ee.filters;
-import static org.apache.shiro.ee.filters.FormResubmitSupport.hasFacesContext;
+import static org.apache.shiro.ee.listeners.IniEnvironment.hasFacesContext;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
diff --git
a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/EnvironmentLoaderListener.java
b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/EnvironmentLoaderListener.java
index 75f68a19c..d7352688b 100644
---
a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/EnvironmentLoaderListener.java
+++
b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/EnvironmentLoaderListener.java
@@ -24,8 +24,13 @@ import javax.servlet.ServletContextListener;
import javax.servlet.SessionTrackingMode;
import javax.servlet.annotation.WebListener;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.web.env.EnvironmentLoader;
import org.apache.shiro.web.env.WebEnvironment;
+import org.apache.shiro.web.mgt.CookieRememberMeManager;
+import org.omnifaces.util.Faces;
+import static org.apache.shiro.ee.listeners.IniEnvironment.hasFacesContext;
/**
* Automatic, adds ability to disable via system property
@@ -74,7 +79,7 @@ public class EnvironmentLoaderListener extends
EnvironmentLoader implements Serv
}
@Override
- @SuppressWarnings("checkstyle:NPathComplexity")
+ @SuppressWarnings({"checkstyle:NPathComplexity",
"checkstyle:CyclomaticComplexity"})
public void contextInitialized(ServletContextEvent sce) {
if
(Boolean.parseBoolean(sce.getServletContext().getInitParameter(SHIRO_EE_DISABLED_PARAM)))
{
sce.getServletContext().setAttribute(SHIRO_EE_DISABLED_PARAM,
Boolean.TRUE);
@@ -108,7 +113,17 @@ public class EnvironmentLoaderListener extends
EnvironmentLoader implements Serv
modifySessionTrackingConfiguration(sce);
}
- initEnvironment(sce.getServletContext());
+ WebEnvironment environment =
initEnvironment(sce.getServletContext());
+ if (hasFacesContext() && Faces.isDevelopment()
+ &&
SecurityUtils.unwrapSecurityManager(environment.getWebSecurityManager(),
DefaultSecurityManager.class)
+ .getRememberMeManager() instanceof
CookieRememberMeManager) {
+ var rememberMeManager = (CookieRememberMeManager) SecurityUtils
+
.unwrapSecurityManager(environment.getWebSecurityManager(),
DefaultSecurityManager.class)
+ .getRememberMeManager();
+ if (!rememberMeManager.isSecureInDevMode()) {
+ rememberMeManager.getCookie().setSecure(false);
+ }
+ }
}
}
diff --git
a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/IniEnvironment.java
b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/IniEnvironment.java
index 46c0d9ff3..0d1a1a962 100644
---
a/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/IniEnvironment.java
+++
b/support/jakarta-ee/src/main/java/org/apache/shiro/ee/listeners/IniEnvironment.java
@@ -35,6 +35,7 @@ import org.apache.shiro.web.env.IniWebEnvironment;
import org.apache.shiro.web.filter.mgt.DefaultFilter;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.omnifaces.util.Beans;
+import org.omnifaces.util.Faces;
import org.omnifaces.util.Lazy;
import static org.omnifaces.util.Utils.isBlank;
@@ -104,6 +105,14 @@ public class IniEnvironment extends IniWebEnvironment {
}
}
+ public static boolean hasFacesContext() {
+ try {
+ return Faces.hasContext();
+ } catch (Throwable e) {
+ return false;
+ }
+ }
+
@Override
protected Ini getFrameworkIni() {
if (otherConfigLocation != null) {
diff --git
a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
index 2defde5d2..6c73448f1 100644
---
a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
+++
b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
@@ -84,10 +84,10 @@ public class AbstractShiroWebConfiguration extends
AbstractShiroConfiguration {
@Value("#{ @environment['shiro.rememberMeManager.cookie.domain'] ?: null
}")
protected String rememberMeCookieDomain;
- @Value("#{ @environment['shiro.rememberMeManager.cookie.path'] ?: null }")
+ @Value("#{ @environment['shiro.rememberMeManager.cookie.path'] ?:
T(org.apache.shiro.web.servlet.Cookie).ROOT_PATH } }")
protected String rememberMeCookiePath;
- @Value("#{ @environment['shiro.rememberMeManager.cookie.secure'] ?: false
}")
+ @Value("#{ @environment['shiro.rememberMeManager.cookie.secure'] ?: true
}")
protected boolean rememberMeCookieSecure;
@Value("#{ @environment['shiro.rememberMeManager.cookie.sameSite'] ?:"
diff --git
a/web/src/main/java/org/apache/shiro/web/mgt/CookieRememberMeManager.java
b/web/src/main/java/org/apache/shiro/web/mgt/CookieRememberMeManager.java
index f44d1ae2c..7e58d1e11 100644
--- a/web/src/main/java/org/apache/shiro/web/mgt/CookieRememberMeManager.java
+++ b/web/src/main/java/org/apache/shiro/web/mgt/CookieRememberMeManager.java
@@ -76,10 +76,12 @@ public class CookieRememberMeManager extends
AbstractRememberMeManager {
* The default name of the underlying rememberMe cookie which is {@code
rememberMe}.
*/
public static final String DEFAULT_REMEMBER_ME_COOKIE_NAME = "rememberMe";
+ public static final String REMEMBER_ME_SECURE_COOKIE_DISABLED =
"org.apache.shiro.rememberMe.secure.disabled";
private static final Logger LOGGER =
LoggerFactory.getLogger(CookieRememberMeManager.class);
private Cookie cookie;
+ private boolean secureInDevMode = true;
/**
* Constructs a new {@code CookieRememberMeManager} with a default {@code
rememberMe} cookie template.
@@ -128,6 +130,33 @@ public class CookieRememberMeManager extends
AbstractRememberMeManager {
this.cookie = cookie;
}
+ /**
+ * Returns {@code true} if the rememberMe cookie should be marked as
secure when the application is running in
+ * development mode. This is a convenience method that allows users to
set the rememberMe cookie as secure in
+ * production environments but not in development environments where SSL
is often not used.
+ * The default value is {@code true}.
+ * @return {@code true} if the rememberMe cookie should be marked as
secure when the application is running in
+ * development mode, {@code false} otherwise (the default value is {@code
true}).
+ * @since 2.1.1
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public boolean isSecureInDevMode() {
+ return secureInDevMode;
+ }
+
+ /**
+ * Sets whether the rememberMe cookie should be marked as secure when the
application is running in development mode.
+ * This is a convenience method that allows users to set the rememberMe
cookie as secure in production environments but not
+ * in development environments where SSL is often not used. The default
value is {@code true}.
+ * @param secureInDevMode set to {@code true} if the rememberMe cookie
should be marked as secure when the
+ * application is running in development mode, {@code false} otherwise
(the default value is {@code true}).
+ * @since 2.1.1
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public void setSecureInDevMode(boolean secureInDevMode) {
+ this.secureInDevMode = secureInDevMode;
+ }
+
/**
* Base64-encodes the specified serialized byte array and sets that
base64-encoded String as the cookie value.
* <p/>
@@ -313,6 +342,9 @@ public class CookieRememberMeManager extends
AbstractRememberMeManager {
private Cookie createDefaultCookie() {
Cookie cookie = new SimpleCookie(DEFAULT_REMEMBER_ME_COOKIE_NAME);
cookie.setHttpOnly(true);
+ if (!Boolean.getBoolean(REMEMBER_ME_SECURE_COOKIE_DISABLED)) {
+ cookie.setSecure(true);
+ }
//One year should be long enough - most sites won't object to
requiring a user to log in if they haven't visited
//in a year:
cookie.setMaxAge(Cookie.ONE_YEAR);