This is an automated email from the ASF dual-hosted git repository.
Aias00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new fb46e7d062 fix: Log desensitization silently replaces non-JSON
bodies/query stri… (#6943)
fb46e7d062 is described below
commit fb46e7d062c71d2419b53163986dbb381f733b68
Author: hengyuss <[email protected]>
AuthorDate: Sat Sep 5 23:42:13 2026 +0800
fix: Log desensitization silently replaces non-JSON bodies/query stri…
(#6943)
* fix: Log desensitization silently replaces non-JSON bodies/query strings
with {} (data loss)
* fix: fix ci
---------
Co-authored-by: aias00 <[email protected]>
---
.../org/apache/shenyu/common/utils/JsonUtils.java | 16 ++++++
.../apache/shenyu/common/utils/JsonUtilsTest.java | 8 +++
.../common/collector/AbstractLogCollector.java | 3 +-
.../api/utils/DataDesensitizeUtils.java | 57 ++++++++++++++++++++--
.../api/utils/DataDesensitizeUtilsTest.java | 30 ++++++++++--
5 files changed, 105 insertions(+), 9 deletions(-)
diff --git
a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/JsonUtils.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/JsonUtils.java
index 391ae6b698..9336f57171 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/JsonUtils.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/JsonUtils.java
@@ -48,6 +48,7 @@ import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Optional;
/**
* JsonUtils.
@@ -161,6 +162,21 @@ public final class JsonUtils {
}
}
+ /**
+ * Try to convert a JSON object string to Map.
+ *
+ * @param json the JSON object string
+ * @return the converted map, or empty when the source is not a JSON object
+ */
+ public static Optional<Map<String, Object>> tryJsonToMap(final String
json) {
+ try {
+ final MapType mapType =
MAPPER.getTypeFactory().constructMapType(LinkedHashMap.class, String.class,
Object.class);
+ return Optional.of(MAPPER.readValue(json, mapType));
+ } catch (IOException e) {
+ return Optional.empty();
+ }
+ }
+
/**
* String to Object.
*
diff --git
a/shenyu-common/src/test/java/org/apache/shenyu/common/utils/JsonUtilsTest.java
b/shenyu-common/src/test/java/org/apache/shenyu/common/utils/JsonUtilsTest.java
index 826758bdbd..ddc03ec34f 100644
---
a/shenyu-common/src/test/java/org/apache/shenyu/common/utils/JsonUtilsTest.java
+++
b/shenyu-common/src/test/java/org/apache/shenyu/common/utils/JsonUtilsTest.java
@@ -31,6 +31,7 @@ import java.util.Objects;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Test cases for JsonUtils.
@@ -48,6 +49,13 @@ public final class JsonUtilsTest {
+
"\"test_map_0\":\"test_value_0\",\"test_map_7\":\"test_value_7\","
+
"\"test_map_6\":\"test_value_6\",\"test_map_5\":\"test_value_5\",\"test_map_4\":\"test_value_4\"},\"testInt\":100}}";
+ @Test
+ public void tryJsonToMap() {
+ assertEquals("test object",
JsonUtils.tryJsonToMap(EXPECTED_JSON).orElseThrow().get("name"));
+ assertTrue(JsonUtils.tryJsonToMap("plain text").isEmpty());
+ assertTrue(JsonUtils.tryJsonToMap("[1,2,3]").isEmpty());
+ }
+
@Test
public void toJson() {
List<String> testList = new LinkedList<>();
diff --git
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/collector/AbstractLogCollector.java
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/collector/AbstractLogCollector.java
index 93274d5319..9f8024cac0 100644
---
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/collector/AbstractLogCollector.java
+++
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-common/src/main/java/org/apache/shenyu/plugin/logging/common/collector/AbstractLogCollector.java
@@ -47,6 +47,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
import static
org.apache.shenyu.plugin.logging.desensitize.api.utils.DataDesensitizeUtils.desensitizeForBody;
import static
org.apache.shenyu.plugin.logging.desensitize.api.utils.DataDesensitizeUtils.desensitizeForSingleWord;
+import static
org.apache.shenyu.plugin.logging.desensitize.api.utils.DataDesensitizeUtils.desensitizeQueryParams;
/**
* abstract log collector,Contains common methods.
@@ -212,7 +213,7 @@ public abstract class AbstractLogCollector<T extends
AbstractLogConsumeClient<?,
logInfo.setResponseBody(desensitizeForSingleWord(GenericLoggingConstant.RESPONSE_BODY,
logInfo.getResponseBody(), keyWordMatch, desensitizedAlg));
logInfo.setRequestHeader(desensitizeForBody(logInfo.getRequestHeader(),
keyWordMatch, desensitizedAlg));
logInfo.setResponseHeader(desensitizeForBody(logInfo.getResponseHeader(),
keyWordMatch, desensitizedAlg));
- logInfo.setQueryParams(desensitizeForBody(logInfo.getQueryParams(),
keyWordMatch, desensitizedAlg));
+
logInfo.setQueryParams(desensitizeQueryParams(logInfo.getQueryParams(),
keyWordMatch, desensitizedAlg));
logInfo.setRequestBody(desensitizeForBody(logInfo.getRequestBody(),
keyWordMatch, desensitizedAlg));
logInfo.setResponseBody(desensitizeForBody(logInfo.getResponseBody(),
keyWordMatch, desensitizedAlg));
}
diff --git
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-desensitize-api/src/main/java/org/apache/shenyu/plugin/logging/desensitize/api/utils/DataDesensitizeUtils.java
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-desensitize-api/src/main/java/org/apache/shenyu/plugin/logging/desensitize/api/utils/DataDesensitizeUtils.java
index a6687ff069..26189eb99d 100644
---
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-desensitize-api/src/main/java/org/apache/shenyu/plugin/logging/desensitize/api/utils/DataDesensitizeUtils.java
+++
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-desensitize-api/src/main/java/org/apache/shenyu/plugin/logging/desensitize/api/utils/DataDesensitizeUtils.java
@@ -22,8 +22,15 @@ import
org.apache.shenyu.plugin.logging.desensitize.api.factory.DataDesensitizeF
import org.apache.shenyu.plugin.logging.desensitize.api.matcher.KeyWordMatch;
import org.springframework.util.StringUtils;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
/**
* data desensitize utils.
@@ -87,10 +94,14 @@ public final class DataDesensitizeUtils {
public static String desensitizeBody(final boolean desensitized, final
String source,
final KeyWordMatch keyWordMatch, final
String dataDesensitizeAlg) {
if (StringUtils.hasLength(source) && desensitized) {
- Map<String, String> bodyMap = JsonUtils.jsonToMap(source,
String.class);
+ Optional<Map<String, Object>> optionalBodyMap =
JsonUtils.tryJsonToMap(source);
+ if (optionalBodyMap.isEmpty()) {
+ return source;
+ }
+ Map<String, Object> bodyMap = optionalBodyMap.get();
bodyMap.forEach((key, value) -> {
- if (keyWordMatch.matches(key)) {
- bodyMap.put(key,
DataDesensitizeFactory.selectDesensitize(value, dataDesensitizeAlg));
+ if (keyWordMatch.matches(key) && Objects.nonNull(value)) {
+ bodyMap.put(key,
DataDesensitizeFactory.selectDesensitize(String.valueOf(value),
dataDesensitizeAlg));
}
});
return JsonUtils.toJson(bodyMap);
@@ -99,6 +110,46 @@ public final class DataDesensitizeUtils {
}
}
+ /**
+ * Desensitize query parameter values by parameter name.
+ *
+ * @param source query string
+ * @param keyWordMatch keyword match strategy
+ * @param dataDesensitizeAlg desensitize algorithm
+ * @return desensitized query string
+ */
+ public static String desensitizeQueryParams(final String source,
+ final KeyWordMatch
keyWordMatch,
+ final String
dataDesensitizeAlg) {
+ if (!StringUtils.hasLength(source)) {
+ return source;
+ }
+ return Arrays.stream(source.split("&", -1))
+ .map(parameter -> desensitizeQueryParam(parameter,
keyWordMatch, dataDesensitizeAlg))
+ .collect(Collectors.joining("&"));
+ }
+
+ private static String desensitizeQueryParam(final String parameter,
+ final KeyWordMatch
keyWordMatch,
+ final String
dataDesensitizeAlg) {
+ int separatorIndex = parameter.indexOf('=');
+ String rawKey = separatorIndex < 0 ? parameter :
parameter.substring(0, separatorIndex);
+ if (separatorIndex < 0) {
+ return parameter;
+ }
+ try {
+ String key = URLDecoder.decode(rawKey, StandardCharsets.UTF_8);
+ String value =
URLDecoder.decode(parameter.substring(separatorIndex + 1),
StandardCharsets.UTF_8);
+ String desensitizedValue = desensitizeSingleKeyword(true, key,
value, keyWordMatch, dataDesensitizeAlg);
+ if (value.equals(desensitizedValue)) {
+ return parameter;
+ }
+ return rawKey + "=" + URLEncoder.encode(desensitizedValue,
StandardCharsets.UTF_8);
+ } catch (IllegalArgumentException e) {
+ return parameter;
+ }
+ }
+
/**
* desensitize for list data.
*
diff --git
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-desensitize-api/src/test/java/org/apache/shenyu/plugin/logging/desensitize/api/utils/DataDesensitizeUtilsTest.java
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-desensitize-api/src/test/java/org/apache/shenyu/plugin/logging/desensitize/api/utils/DataDesensitizeUtilsTest.java
index 06bcdd6a13..c05c7b859b 100644
---
a/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-desensitize-api/src/test/java/org/apache/shenyu/plugin/logging/desensitize/api/utils/DataDesensitizeUtilsTest.java
+++
b/shenyu-plugin/shenyu-plugin-logging/shenyu-plugin-logging-desensitize-api/src/test/java/org/apache/shenyu/plugin/logging/desensitize/api/utils/DataDesensitizeUtilsTest.java
@@ -25,8 +25,6 @@ import
org.apache.shenyu.plugin.logging.desensitize.api.matcher.KeyWordMatch;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Arrays;
import java.util.HashSet;
@@ -34,7 +32,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-@ExtendWith(MockitoExtension.class)
public class DataDesensitizeUtilsTest {
private static final String JSON_TEXT =
"{\"id\":\"123\",\"name\":\"jack\"}";
@@ -67,9 +64,32 @@ public class DataDesensitizeUtilsTest {
String desensitizedData = DataDesensitizeUtils.desensitizeBody(true,
JSON_TEXT, keyWordMatch,
DataDesensitizeEnum.MD5_ENCRYPT.getDataDesensitizeAlg());
Map<String, String> jsonMap = JsonUtils.jsonToMap(JSON_TEXT,
String.class);
jsonMap.put("name", DigestUtils.md5Hex(jsonMap.get("name")));
- String jsonRet = JsonUtils.toJson(jsonMap);
- Assertions.assertEquals(jsonRet, desensitizedData);
+ Assertions.assertEquals(jsonMap, JsonUtils.jsonToMap(desensitizedData,
String.class));
+ String plainText = "name=jack&message=hello";
+ Assertions.assertEquals(plainText,
DataDesensitizeUtils.desensitizeBody(true, plainText, keyWordMatch,
+ DataDesensitizeEnum.MD5_ENCRYPT.getDataDesensitizeAlg()));
+
+ String xml = "<user><name>jack</name></user>";
+ Assertions.assertEquals(xml,
DataDesensitizeUtils.desensitizeBody(true, xml, keyWordMatch,
+ DataDesensitizeEnum.MD5_ENCRYPT.getDataDesensitizeAlg()));
+
+ String jsonArray = "[1,2,3]";
+ Assertions.assertEquals(jsonArray,
DataDesensitizeUtils.desensitizeBody(true, jsonArray, keyWordMatch,
+ DataDesensitizeEnum.MD5_ENCRYPT.getDataDesensitizeAlg()));
+
+ }
+
+ @Test
+ public void desensitizeQueryParamsTest() {
+ String source = "id=123&name=jack&empty=&debug&name=rose";
+ String jack = DigestUtils.md5Hex("jack");
+ String rose = DigestUtils.md5Hex("rose");
+ Assertions.assertEquals("id=123&name=" + jack + "&empty=&debug&name="
+ rose,
+ DataDesensitizeUtils.desensitizeQueryParams(source,
keyWordMatch,
+
DataDesensitizeEnum.MD5_ENCRYPT.getDataDesensitizeAlg()));
+ Assertions.assertEquals("name=%invalid",
DataDesensitizeUtils.desensitizeQueryParams("name=%invalid", keyWordMatch,
+ DataDesensitizeEnum.MD5_ENCRYPT.getDataDesensitizeAlg()));
}
@Test