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);

Reply via email to