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

Reply via email to