This is an automated email from the ASF dual-hosted git repository.
mridulpathak pushed a commit to branch release24.09
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/release24.09 by this push:
new 7f8ed14757 Improved: Use SecureRandom to generate promo codes, captcha
codes and generated IDs (OFBIZ-13636)
7f8ed14757 is described below
commit 7f8ed14757f384df6eb6b1c7c3ac2c5105578b81
Author: Mridul Pathak <[email protected]>
AuthorDate: Sat Oct 3 13:54:33 2026 +0530
Improved: Use SecureRandom to generate promo codes, captcha codes and
generated IDs (OFBIZ-13636)
Promo codes, captcha codes and the parameter map IDs stored in the session
were generated with the commons-lang RandomStringUtils, which is backed by
java.util.Random and so produces values that can be predicted from earlier ones.
StringUtil now provides randomString(int, String), which picks each
character with SecureRandom, together with the ALPHABETIC_CHARS and
ALPHANUMERIC_CHARS constants, and these three places use it instead. The
character sets and lengths are unchanged.
Thanks: Jacopo Cappellato (jacopoc) for suggesting the fix.
(cherry picked from commit 4a087c8073)
---
.../apache/ofbiz/product/promo/PromoServices.java | 9 +++----
.../org/apache/ofbiz/base/util/StringUtil.java | 29 ++++++++++++++++++++++
.../java/org/apache/ofbiz/base/util/UtilHttp.java | 3 +--
.../java/org/apache/ofbiz/common/CommonEvents.java | 8 +++---
4 files changed, 38 insertions(+), 11 deletions(-)
diff --git
a/applications/product/src/main/java/org/apache/ofbiz/product/promo/PromoServices.java
b/applications/product/src/main/java/org/apache/ofbiz/product/promo/PromoServices.java
index 884d33a4b5..f5cea59ce0 100644
---
a/applications/product/src/main/java/org/apache/ofbiz/product/promo/PromoServices.java
+++
b/applications/product/src/main/java/org/apache/ofbiz/product/promo/PromoServices.java
@@ -31,8 +31,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
-import org.apache.commons.lang.RandomStringUtils;
import org.apache.ofbiz.base.util.Debug;
+import org.apache.ofbiz.base.util.StringUtil;
import org.apache.ofbiz.base.util.UtilDateTime;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilProperties;
@@ -57,8 +57,7 @@ public class PromoServices {
private static final String MODULE = PromoServices.class.getName();
private static final String RESOURCE = "ProductUiLabels";
- private static final char[] SMART_CHARS = {'A', 'B', 'C', 'D', 'E', 'F',
'G', 'H', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
- 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7', '8', '9' };
+ private static final String SMART_CHARS =
"ABCDEFGHKLMNPQRSTUVWXYZ23456789";
public static Map<String, Object>
createProductPromoCodeSet(DispatchContext dctx, Map<String, ? extends Object>
context) {
Locale locale = (Locale) context.get("locale");
@@ -87,9 +86,9 @@ public class PromoServices {
while (!foundUniqueNewCode) {
if (useSmartLayout) {
- newPromoCodeId = RandomStringUtils.random(codeLength,
SMART_CHARS);
+ newPromoCodeId = StringUtil.randomString(codeLength,
SMART_CHARS);
} else if (useNormalLayout) {
- newPromoCodeId =
RandomStringUtils.randomAlphanumeric(codeLength);
+ newPromoCodeId = StringUtil.randomString(codeLength,
StringUtil.ALPHANUMERIC_CHARS);
}
GenericValue existingPromoCode = null;
try {
diff --git
a/framework/base/src/main/java/org/apache/ofbiz/base/util/StringUtil.java
b/framework/base/src/main/java/org/apache/ofbiz/base/util/StringUtil.java
index b5cc4b03a6..2a11b300d9 100644
--- a/framework/base/src/main/java/org/apache/ofbiz/base/util/StringUtil.java
+++ b/framework/base/src/main/java/org/apache/ofbiz/base/util/StringUtil.java
@@ -20,6 +20,7 @@ package org.apache.ofbiz.base.util;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
+import java.security.SecureRandom;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -47,6 +48,12 @@ public final class StringUtil {
public static final StringUtil INSTANCE = new StringUtil();
private static final String MODULE = StringUtil.class.getName();
private static final Map<String, Pattern> SUBSTITUTION_PATTERN_MAP =
createSubstitutionPatternMap();
+ private static final SecureRandom SECURE_RANDOM = new SecureRandom();
+
+ /** The upper and lower case letters, to be used with {@link
#randomString(int, String)} */
+ public static final String ALPHABETIC_CHARS =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ /** The upper and lower case letters and the digits, to be used with
{@link #randomString(int, String)} */
+ public static final String ALPHANUMERIC_CHARS = ALPHABETIC_CHARS +
"0123456789";
private static Map<String, Pattern> createSubstitutionPatternMap() {
Map<String, Pattern> substitutionPatternMap = new LinkedHashMap<>();
// Preserve insertion order
@@ -66,6 +73,28 @@ public final class StringUtil {
return value != null ? value.intern() : null;
}
+ /**
+ * Generates a random string, using a cryptographically strong random
number generator, so that the result
+ * cannot be predicted. Use this for codes and identifiers that have to be
hard to guess.
+ * @param length the length of the string to generate
+ * @param chars the characters the string is made of, each one has the
same probability to be picked
+ * @return a random string of the given length
+ * @throws IllegalArgumentException if the length is negative or there are
no characters to choose from
+ */
+ public static String randomString(int length, String chars) {
+ if (length < 0) {
+ throw new IllegalArgumentException("The length must not be
negative: " + length);
+ }
+ if (chars == null || chars.isEmpty()) {
+ throw new IllegalArgumentException("There must be characters to
choose from");
+ }
+ StringBuilder sb = new StringBuilder(length);
+ for (int i = 0; i < length; i++) {
+ sb.append(chars.charAt(SECURE_RANDOM.nextInt(chars.length())));
+ }
+ return sb.toString();
+ }
+
/**
* Replaces all occurrences of oldString in mainString with newString
* @param mainString The original string
diff --git
a/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilHttp.java
b/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilHttp.java
index 27b7eef54a..1f976978a3 100644
--- a/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilHttp.java
+++ b/framework/base/src/main/java/org/apache/ofbiz/base/util/UtilHttp.java
@@ -72,7 +72,6 @@ import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.apache.commons.lang.RandomStringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.ofbiz.entity.Delegator;
@@ -1680,7 +1679,7 @@ public final class UtilHttp {
session.setAttribute("_PARAM_MAP_STORE_", paramMapStore);
}
Map<String, Object> parameters = getParameterMap(request);
- String paramMapId = RandomStringUtils.randomAlphanumeric(10);
+ String paramMapId = StringUtil.randomString(10,
StringUtil.ALPHANUMERIC_CHARS);
paramMapStore.put(paramMapId, parameters);
return paramMapId;
}
diff --git
a/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java
b/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java
index a703401e79..c5e38dabf7 100644
--- a/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java
+++ b/framework/common/src/main/java/org/apache/ofbiz/common/CommonEvents.java
@@ -42,12 +42,12 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
-import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ofbiz.base.lang.JSON;
import org.apache.ofbiz.base.location.ComponentLocationResolver;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.GeneralException;
+import org.apache.ofbiz.base.util.StringUtil;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilHttp;
import org.apache.ofbiz.base.util.UtilProperties;
@@ -285,8 +285,8 @@ public class CommonEvents {
final int height = Integer.parseInt(captchaSizeConfigs[1]);
final int width = Integer.parseInt(captchaSizeConfigs[2]);
final int charsToPrint =
UtilProperties.getPropertyAsInteger("captcha", "captcha.code_length", 6);
- final char[] availableChars = EntityUtilProperties
- .getPropertyValue("captcha", "captcha.characters",
delegator).toCharArray();
+ final String availableChars = EntityUtilProperties
+ .getPropertyValue("captcha", "captcha.characters",
delegator);
// It is possible to pass the font size, image width and height
with the request as well
Color backgroundColor = Color.gray;
@@ -319,7 +319,7 @@ public class CommonEvents {
int maxAdvance = fontMetrics.getMaxAdvance();
int fontHeight = fontMetrics.getHeight();
- String captchaCode = RandomStringUtils.random(6, availableChars);
+ String captchaCode = StringUtil.randomString(6, availableChars);
float spaceForLetters = -horizMargin * 2 + width;
float spacePerChar = spaceForLetters / (charsToPrint - 1.0f);