This is an automated email from the ASF dual-hosted git repository.

kusal pushed a commit to branch WW-5439-fix-dev-mode
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 6e07b01b65e5067c311ad5eed24e5a1f0524850d
Author: Kusal Kithul-Godage <g...@kusal.io>
AuthorDate: Mon Jul 8 18:42:06 2024 +1000

    WW-5439 Move Dev Mode security configuration
---
 .../com/opensymphony/xwork2/ognl/OgnlUtil.java     | 54 +++++++++++-----------
 .../xwork2/ognl/SecurityMemberAccess.java          | 50 ++++++++++++++++++++
 2 files changed, 76 insertions(+), 28 deletions(-)

diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java 
b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
index 681aac57d..1fee7a257 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java
@@ -47,7 +47,6 @@ import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.regex.Pattern;
 
 import static com.opensymphony.xwork2.util.ConfigParseUtil.toClassesSet;
@@ -68,9 +67,6 @@ public class OgnlUtil {
 
     private static final Logger LOG = LogManager.getLogger(OgnlUtil.class);
 
-    // Flag used to reduce flooding logs with WARNs about using DevMode 
excluded packages
-    private final AtomicBoolean warnReported = new AtomicBoolean(false);
-
     private final OgnlCache<String, Object> expressionCache;
     private final OgnlCache<Class<?>, BeanInfo> beanInfoCache;
     private TypeConverter defaultConverter;
@@ -80,11 +76,6 @@ public class OgnlUtil {
     private boolean enableExpressionCache = true;
     private boolean enableEvalExpression;
 
-    private String devModeExcludedClasses = "";
-    private String devModeExcludedPackageNamePatterns = "";
-    private String devModeExcludedPackageNames = "";
-    private String devModeExcludedPackageExemptClasses = "";
-
     private Container container;
 
     /**
@@ -124,6 +115,7 @@ public class OgnlUtil {
     @Inject(StrutsConstants.STRUTS_DEVMODE)
     protected void setDevMode(String mode) {
         this.devMode = BooleanUtils.toBoolean(mode);
+        LOG.warn("Working in devMode, using devMode excluded classes and 
packages!");
     }
 
     @Inject(value = StrutsConstants.STRUTS_OGNL_ENABLE_EXPRESSION_CACHE, 
required = false)
@@ -164,9 +156,12 @@ public class OgnlUtil {
         // Must be set directly on SecurityMemberAccess
     }
 
-    @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required 
= false)
+    /**
+     * @deprecated since 6.5.0, no replacement.
+     */
+    @Deprecated
     protected void setDevModeExcludedClasses(String commaDelimitedClasses) {
-        this.devModeExcludedClasses = commaDelimitedClasses;
+        // Must be set directly on SecurityMemberAccess
     }
 
     /**
@@ -177,9 +172,12 @@ public class OgnlUtil {
         // Must be set directly on SecurityMemberAccess
     }
 
-    @Inject(value = 
StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, required = 
false)
+    /**
+     * @deprecated since 6.5.0, no replacement.
+     */
+    @Deprecated
     protected void setDevModeExcludedPackageNamePatterns(String 
commaDelimitedPackagePatterns) {
-        this.devModeExcludedPackageNamePatterns = 
commaDelimitedPackagePatterns;
+        // Must be set directly on SecurityMemberAccess
     }
 
     /**
@@ -190,9 +188,12 @@ public class OgnlUtil {
         // Must be set directly on SecurityMemberAccess
     }
 
-    @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES, 
required = false)
+    /**
+     * @deprecated since 6.5.0, no replacement.
+     */
+    @Deprecated
     protected void setDevModeExcludedPackageNames(String 
commaDelimitedPackageNames) {
-        this.devModeExcludedPackageNames = commaDelimitedPackageNames;
+        // Must be set directly on SecurityMemberAccess
     }
 
     /**
@@ -203,9 +204,12 @@ public class OgnlUtil {
         // Must be set directly on SecurityMemberAccess
     }
 
-    @Inject(value = 
StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_EXEMPT_CLASSES, required = 
false)
+    /**
+     * @deprecated since 6.5.0, no replacement.
+     */
+    @Deprecated
     public void setDevModeExcludedPackageExemptClasses(String 
commaDelimitedClasses) {
-        this.devModeExcludedPackageExemptClasses = commaDelimitedClasses;
+        // Must be set directly on SecurityMemberAccess
     }
 
     /**
@@ -856,6 +860,11 @@ public class OgnlUtil {
         return createDefaultContext(root, null);
     }
 
+    /**
+     * Note that the allowlist capability is not enforced by the {@link 
OgnlContext} returned by this method. Currently,
+     * this context is only leveraged by some public methods on {@link 
OgnlUtil} which are called by
+     * {@link OgnlReflectionProvider}.
+     */
     protected Map<String, Object> createDefaultContext(Object root, 
ClassResolver resolver) {
         if (resolver == null) {
             resolver = container.getInstance(RootAccessor.class);
@@ -867,17 +876,6 @@ public class OgnlUtil {
         SecurityMemberAccess memberAccess = 
container.getInstance(SecurityMemberAccess.class);
         memberAccess.useEnforceAllowlistEnabled(Boolean.FALSE.toString());
 
-        if (devMode) {
-            if (!warnReported.get()) {
-                warnReported.set(true);
-                LOG.warn("Working in devMode, using devMode excluded classes 
and packages!");
-            }
-            memberAccess.useExcludedClasses(devModeExcludedClasses);
-            
memberAccess.useExcludedPackageNamePatterns(devModeExcludedPackageNamePatterns);
-            memberAccess.useExcludedPackageNames(devModeExcludedPackageNames);
-            
memberAccess.useExcludedPackageExemptClasses(devModeExcludedPackageExemptClasses);
-        }
-
         return Ognl.createDefaultContext(root, memberAccess, resolver, 
defaultConverter);
     }
 
diff --git 
a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java 
b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java
index f882b2c58..f2eab0c3e 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java
@@ -77,16 +77,27 @@ public class SecurityMemberAccess implements MemberAccess {
 
     private final ProviderAllowlist providerAllowlist;
     private final ThreadAllowlist threadAllowlist;
+
     private boolean allowStaticFieldAccess = true;
+
     private Set<Pattern> excludeProperties = emptySet();
     private Set<Pattern> acceptProperties = emptySet();
+
     private Set<String> excludedClasses = unmodifiableSet(new 
HashSet<>(singletonList(Object.class.getName())));
     private Set<Pattern> excludedPackageNamePatterns = emptySet();
     private Set<String> excludedPackageNames = emptySet();
     private Set<String> excludedPackageExemptClasses = emptySet();
+
+    private boolean devMode;
+    private Set<String> devModeExcludedClasses = unmodifiableSet(new 
HashSet<>(singletonList(Object.class.getName())));
+    private Set<Pattern> devModeExcludedPackageNamePatterns = emptySet();
+    private Set<String> devModeExcludedPackageNames = emptySet();
+    private Set<String> devModeExcludedPackageExemptClasses = emptySet();
+
     private boolean enforceAllowlistEnabled = false;
     private Set<Class<?>> allowlistClasses = emptySet();
     private Set<String> allowlistPackageNames = emptySet();
+
     private boolean disallowProxyObjectAccess = false;
     private boolean disallowProxyMemberAccess = false;
     private boolean disallowDefaultPackageAccess = false;
@@ -460,4 +471,43 @@ public class SecurityMemberAccess implements MemberAccess {
     public void useDisallowDefaultPackageAccess(String 
disallowDefaultPackageAccess) {
         this.disallowDefaultPackageAccess = 
BooleanUtils.toBoolean(disallowDefaultPackageAccess);
     }
+
+    @Inject(StrutsConstants.STRUTS_DEVMODE)
+    protected void setDevMode(String devMode) {
+        this.devMode = BooleanUtils.toBoolean(devMode);
+        setDevModeConfiguration();
+    }
+
+    @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_CLASSES, required 
= false)
+    public void useDevModeExcludedClasses(String commaDelimitedClasses) {
+        this.devModeExcludedClasses = toNewClassesSet(devModeExcludedClasses, 
commaDelimitedClasses);
+        setDevModeConfiguration();
+    }
+
+    @Inject(value = 
StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS, required = 
false)
+    public void useDevModeExcludedPackageNamePatterns(String 
commaDelimitedPackagePatterns) {
+        this.devModeExcludedPackageNamePatterns = 
toNewPatternsSet(devModeExcludedPackageNamePatterns, 
commaDelimitedPackagePatterns);
+        setDevModeConfiguration();
+    }
+
+    @Inject(value = StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES, 
required = false)
+    public void useDevModeExcludedPackageNames(String 
commaDelimitedPackageNames) {
+        this.devModeExcludedPackageNames = 
toNewPackageNamesSet(devModeExcludedPackageNames, commaDelimitedPackageNames);
+        setDevModeConfiguration();
+    }
+
+    @Inject(value = 
StrutsConstants.STRUTS_DEV_MODE_EXCLUDED_PACKAGE_EXEMPT_CLASSES, required = 
false)
+    public void useDevModeExcludedPackageExemptClasses(String 
commaDelimitedClasses) {
+        this.devModeExcludedPackageExemptClasses = 
toClassesSet(commaDelimitedClasses);
+        setDevModeConfiguration();
+    }
+
+    private void setDevModeConfiguration() {
+        if (this.devMode) {
+            excludedClasses = devModeExcludedClasses;
+            excludedPackageNamePatterns = devModeExcludedPackageNamePatterns;
+            excludedPackageNames = devModeExcludedPackageNames;
+            excludedPackageExemptClasses = devModeExcludedPackageExemptClasses;
+        }
+    }
 }

Reply via email to