You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by li...@apache.org on 2022/12/07 01:18:02 UTC
[shenyu] branch master updated: [type:refactor]Decoupled and enhanced SignUtil (#4234)
This is an automated email from the ASF dual-hosted git repository.
likeguo 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 25aa30c1b [type:refactor]Decoupled and enhanced SignUtil (#4234)
25aa30c1b is described below
commit 25aa30c1b095176dcc5d4febeb5d2e46e997f4a2
Author: 愿凌飞 <ti...@foxmail.com>
AuthorDate: Wed Dec 7 09:17:52 2022 +0800
[type:refactor]Decoupled and enhanced SignUtil (#4234)
* [type:refactor]Decoupled and enhanced SignUtil
* [type:refactor]fix test
* refactor
* refactor
* fix
* fix
* fix
---
.../org/apache/shenyu/common/utils/HmacUtils.java | 66 ++++++++++++
.../org/apache/shenyu/common/utils/MapUtils.java | 27 +++--
.../org/apache/shenyu/common/utils/SignUtils.java | 77 ++++++--------
.../apache/shenyu/common/utils/MapUtilsTest.java | 31 +++---
.../apache/shenyu/common/utils/SignUtilsTest.java | 51 ++++-----
.../test/http/combination/SignPluginTest.java | 29 +++++-
.../plugin/sign/api/DefaultSignProvider.java | 26 ++++-
.../plugin/sign/service/DefaultSignService.java | 6 +-
.../sign/service/DefaultSignServiceTest.java | 26 ++++-
.../plugin/sign/sign/DefaultSignProviderTest.java | 10 +-
.../web/controller/LocalPluginController.java | 114 ++++++++++-----------
11 files changed, 280 insertions(+), 183 deletions(-)
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/HmacUtils.java b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/HmacUtils.java
new file mode 100644
index 000000000..6450e70ff
--- /dev/null
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/HmacUtils.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.common.utils;
+
+import org.apache.commons.codec.digest.HmacAlgorithms;
+
+/**
+ * HmacUtils.
+ */
+public class HmacUtils {
+
+ /**
+ * Returns a HmacMd5 Message Authentication Code (MAC) as hex string (lowercase).
+ *
+ * @param key The key
+ * @param valueToDigest The value to use to digest
+ * @return Message Authentication Code
+ */
+ public static String hmacMd5Hex(final String key, final String valueToDigest) {
+ return getHmacHex(HmacAlgorithms.HMAC_MD5, key, valueToDigest);
+ }
+
+ /**
+ * Returns a HmacSha256 Message Authentication Code (MAC) as hex string (lowercase).
+ *
+ * @param key The key
+ * @param valueToDigest The value to use to digest
+ * @return Message Authentication Code
+ */
+ public static String hmacSha256Hex(final String key, final String valueToDigest) {
+ return getHmacHex(HmacAlgorithms.HMAC_SHA_256, key, valueToDigest);
+
+ }
+
+ /**
+ * Returns a HmacSha512 Message Authentication Code (MAC) as hex string (lowercase).
+ *
+ * @param key The key
+ * @param valueToDigest The value to use to digest
+ * @return Message Authentication Code
+ */
+ public static String hmacSha512Hex(final String key, final String valueToDigest) {
+ return getHmacHex(HmacAlgorithms.HMAC_SHA_512, key, valueToDigest);
+ }
+
+ private static String getHmacHex(final HmacAlgorithms algorithm, final String key, final String valueToDigest) {
+ return new org.apache.commons.codec.digest.HmacUtils(algorithm, key)
+ .hmacHex(valueToDigest);
+ }
+
+}
diff --git a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/MapUtils.java
similarity index 60%
copy from shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java
copy to shenyu-common/src/main/java/org/apache/shenyu/common/utils/MapUtils.java
index af556da5b..b0801dd60 100644
--- a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/MapUtils.java
@@ -15,27 +15,24 @@
* limitations under the License.
*/
-package org.apache.shenyu.plugin.sign.api;
-
-import org.apache.shenyu.common.utils.SignUtils;
+package org.apache.shenyu.common.utils;
import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
-/**
- * The Sign plugin default signer.
- */
-public class DefaultSignProvider implements SignProvider {
+public class MapUtils {
/**
- * acquired sign.
+ * Transform to string map.
*
- * @param signKey sign key
- * @param jsonParams json params
- * @param queryParams url query params
- * @return sign
+ * @param map source map
+ * @return string map
*/
- @Override
- public String generateSign(final String signKey, final Map<String, String> jsonParams, final Map<String, String> queryParams) {
- return SignUtils.generateSign(signKey, jsonParams, queryParams);
+ public static Map<String, String> transStringMap(final Map<String, Object> map) {
+ return Optional.ofNullable(map)
+ .map(m -> m.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> Objects.toString(e.getValue(), null))))
+ .orElse(null);
}
}
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SignUtils.java b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SignUtils.java
index ae137c8bf..04830a345 100644
--- a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SignUtils.java
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SignUtils.java
@@ -17,53 +17,51 @@
package org.apache.shenyu.common.utils;
-import java.util.Comparator;
+import com.google.common.collect.ImmutableMap;
+
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
-import java.util.stream.Collectors;
/**
* SignUtils.
*/
public final class SignUtils {
- /**
- * acquired sign.
- *
- * @param signKey sign key
- * @param jsonParams json params
- * @param queryParams url query params
- * @return sign
- */
- public static String generateSign(final String signKey, final Map<String, String> jsonParams, final Map<String, String> queryParams) {
- final String jsonSign = Optional.ofNullable(jsonParams).map(e -> e.keySet().stream()
- .sorted(Comparator.naturalOrder())
- .map(key -> String.join("", key, jsonParams.get(key)))
- .collect(Collectors.joining()).trim())
- .orElse("");
- final String querySign = Optional.ofNullable(queryParams).map(e -> e.keySet().stream()
- .sorted(Comparator.naturalOrder())
- .map(key -> String.join("", key, queryParams.get(key)))
- .collect(Collectors.joining()).trim())
- .orElse("");
- final String sign = String.join("", jsonSign, querySign, signKey);
- // TODO this is a risk for error charset coding with getBytes
- return DigestUtils.md5Hex(sign.getBytes()).toUpperCase();
- }
+ public static final String SIGN_MD5 = "MD5";
+
+ public static final String SIGN_HMD5 = "HMD5";
+
+ public static final String SIGN_HS256 = "HS256";
+
+ public static final String SIGN_HS512 = "HS512";
+
+ private static final Map<String, SignFunction> SIGN_FUNCTION_MAP = ImmutableMap.of(
+ SIGN_MD5, (key, data) -> DigestUtils.md5Hex(data + key),
+ SIGN_HMD5, HmacUtils::hmacMd5Hex,
+ SIGN_HS256, HmacUtils::hmacSha256Hex,
+ SIGN_HS512, HmacUtils::hmacSha512Hex
+ );
/**
- * isValid.
+ * Returns signature of data as hex string (lowercase).
*
- * @param sign sign
- * @param jsonParams json params
- * @param queryParams url query params
- * @param signKey sign key
- * @return boolean
+ * @param algorithmName the name of sign algorithm
+ * @param key key
+ * @param data data to sign
+ * @return signature
+ * @throws NullPointerException if key or data is null
+ * @throws UnsupportedOperationException if algorithmName isn't supported
*/
- public static boolean isValid(final String sign, final Map<String, String> jsonParams, final Map<String, String> queryParams, final String signKey) {
- return Objects.equals(sign, generateSign(signKey, jsonParams, queryParams));
+ public static String sign(final String algorithmName, final String key, final String data) {
+ if (Objects.isNull(key) || Objects.isNull(data)) {
+ throw new NullPointerException("Key or data is null.");
+ }
+
+ return Optional.ofNullable(SIGN_FUNCTION_MAP.get(algorithmName))
+ .orElseThrow(() -> new UnsupportedOperationException("unsupported sign algorithm:" + algorithmName))
+ .sign(key, data);
}
/**
@@ -75,16 +73,9 @@ public final class SignUtils {
return UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
}
- /**
- * Transform to string map.
- *
- * @param map source map
- * @return string map
- */
- public static Map<String, String> transStringMap(final Map<String, Object> map) {
- return Optional.ofNullable(map)
- .map(m -> m.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> Objects.toString(e.getValue(), null))))
- .orElse(null);
+ @FunctionalInterface
+ private interface SignFunction {
+ String sign(String key, String data);
}
}
diff --git a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java b/shenyu-common/src/test/java/org/apache/shenyu/common/utils/MapUtilsTest.java
similarity index 58%
copy from shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java
copy to shenyu-common/src/test/java/org/apache/shenyu/common/utils/MapUtilsTest.java
index af556da5b..29c097acc 100644
--- a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java
+++ b/shenyu-common/src/test/java/org/apache/shenyu/common/utils/MapUtilsTest.java
@@ -15,27 +15,24 @@
* limitations under the License.
*/
-package org.apache.shenyu.plugin.sign.api;
+package org.apache.shenyu.common.utils;
-import org.apache.shenyu.common.utils.SignUtils;
+import org.junit.jupiter.api.Test;
+import java.util.HashMap;
import java.util.Map;
-/**
- * The Sign plugin default signer.
- */
-public class DefaultSignProvider implements SignProvider {
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class MapUtilsTest {
- /**
- * acquired sign.
- *
- * @param signKey sign key
- * @param jsonParams json params
- * @param queryParams url query params
- * @return sign
- */
- @Override
- public String generateSign(final String signKey, final Map<String, String> jsonParams, final Map<String, String> queryParams) {
- return SignUtils.generateSign(signKey, jsonParams, queryParams);
+ @Test
+ public void testTransStringMap() {
+ Map<String, Object> jsonParams = new HashMap<>();
+ jsonParams.put("a", 1);
+ jsonParams.put("b", 2);
+ Map<String, String> stringStringMap = MapUtils.transStringMap(jsonParams);
+ assertEquals(stringStringMap.get("a").getClass(), String.class);
+ assertEquals(stringStringMap.get("a"), "1");
}
}
diff --git a/shenyu-common/src/test/java/org/apache/shenyu/common/utils/SignUtilsTest.java b/shenyu-common/src/test/java/org/apache/shenyu/common/utils/SignUtilsTest.java
index 08fd3d644..a1330f2a2 100644
--- a/shenyu-common/src/test/java/org/apache/shenyu/common/utils/SignUtilsTest.java
+++ b/shenyu-common/src/test/java/org/apache/shenyu/common/utils/SignUtilsTest.java
@@ -19,12 +19,10 @@ package org.apache.shenyu.common.utils;
import org.junit.jupiter.api.Test;
-import java.util.HashMap;
-import java.util.Map;
-
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrowsExactly;
/**
* Test cases for SignUtils.
@@ -32,40 +30,31 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public final class SignUtilsTest {
@Test
- public void testGenerateSign() {
- Map<String, String> jsonParams = new HashMap<>();
- jsonParams.put("a", "1");
- jsonParams.put("b", "2");
- Map<String, String> queryParams = new HashMap<>();
- jsonParams.put("a", "1");
- jsonParams.put("b", "2");
- assertNotNull(SignUtils.generateSign("test", jsonParams, queryParams));
+ public void testGenerateMd5Sign() {
+
+ assertThat(SignUtils.sign(SignUtils.SIGN_MD5, "test", "a1b2"),
+ is("7aa98f7d67f8e4730e2d1d3902295ce6"));
}
@Test
- public void testValid() {
- final String sign = "7AA98F7D67F8E4730E2D1D3902295CE6";
- Map<String, String> jsonParams = new HashMap<>();
- jsonParams.put("a", "1");
- jsonParams.put("b", "2");
- Map<String, String> queryParams = new HashMap<>();
- jsonParams.put("a", "1");
- jsonParams.put("b", "2");
- assertTrue(SignUtils.isValid(sign, jsonParams, queryParams, "test"));
+ public void testGeneratesSignWithNullKeyOrNullData() {
+
+ assertThrowsExactly(NullPointerException.class,
+ () -> SignUtils.sign(SignUtils.SIGN_HS256, "key", null));
+
+ assertThrowsExactly(NullPointerException.class,
+ () -> SignUtils.sign(SignUtils.SIGN_HS256, null, "data"));
}
@Test
- public void testGenerateKey() {
- assertNotNull(SignUtils.generateKey());
+ public void testGeneratesSignWithUnsupportedAlgorithm() {
+
+ assertThrowsExactly(UnsupportedOperationException.class,
+ () -> SignUtils.sign("supported_algorithm", "key", "data"));
}
@Test
- public void testTransStringMap() {
- Map<String, Object> jsonParams = new HashMap<>();
- jsonParams.put("a", "1");
- jsonParams.put("b", "2");
- Map<String, String> stringStringMap = SignUtils.transStringMap(jsonParams);
- assertEquals(stringStringMap.get("a").getClass(), String.class);
- assertEquals(stringStringMap.get("a"), "1");
+ public void testGenerateKey() {
+ assertNotNull(SignUtils.generateKey());
}
}
diff --git a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/SignPluginTest.java b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/SignPluginTest.java
index 2bedcb367..edc19529a 100644
--- a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/SignPluginTest.java
+++ b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/SignPluginTest.java
@@ -38,8 +38,11 @@ import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -173,8 +176,7 @@ public final class SignPluginTest extends AbstractPluginDataInit {
private Map<String, Object> buildHeadersMap(final String timestamp, final String path, final String appKey,
final String appSecret, final String version) {
- String extSignKey = String.join("", Constants.PATH, path, Constants.TIMESTAMP, timestamp, Constants.VERSION, version, appSecret);
- String sign = SignUtils.generateSign(extSignKey, null, null);
+ String sign = buildSign(appSecret, version, timestamp, path, null, null);
Map<String, Object> headers = Maps.newHashMapWithExpectedSize(4);
headers.put("timestamp", timestamp);
headers.put("appKey", appKey);
@@ -185,9 +187,7 @@ public final class SignPluginTest extends AbstractPluginDataInit {
private Map<String, Object> buildHeadersMapQueryParam(final String timestamp, final String path, final String appKey,
final String appSecret, final String version, final Map<String, String> queryParam) {
- String extSignKey = String.join("", Constants.PATH, path, Constants.TIMESTAMP, timestamp, Constants.VERSION, version, appSecret);
- String sign = SignUtils.generateSign(extSignKey, null, queryParam);
-
+ String sign = buildSign(appSecret, version, timestamp, path, null, queryParam);
Map<String, Object> headers = Maps.newHashMapWithExpectedSize(4);
headers.put("timestamp", timestamp);
headers.put("appKey", appKey);
@@ -258,4 +258,23 @@ public final class SignPluginTest extends AbstractPluginDataInit {
cleanPluginData(PluginEnum.SIGN.getName());
cleanAuthData(APP_KEY);
}
+
+ private String buildSign(final String signKey, final String version, final String timeStamp, final String path, final Map<String, String> jsonParams, final Map<String, String> queryParams) {
+
+ final String jsonSign = Optional.ofNullable(jsonParams).map(e -> e.keySet().stream()
+ .sorted(Comparator.naturalOrder())
+ .map(key -> String.join("", key, jsonParams.get(key)))
+ .collect(Collectors.joining()).trim())
+ .orElse("");
+
+ final String querySign = Optional.ofNullable(queryParams).map(e -> e.keySet().stream()
+ .sorted(Comparator.naturalOrder())
+ .map(key -> String.join("", key, queryParams.get(key)))
+ .collect(Collectors.joining()).trim())
+ .orElse("");
+
+ final String extSignKey = String.join("", Constants.PATH, path, Constants.TIMESTAMP, timeStamp, Constants.VERSION, version, signKey);
+ final String data = String.join("", jsonSign, querySign);
+ return SignUtils.sign(SignUtils.SIGN_MD5, extSignKey, data).toUpperCase();
+ }
}
diff --git a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java
index af556da5b..c0ad805ef 100644
--- a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java
+++ b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/DefaultSignProvider.java
@@ -19,7 +19,10 @@ package org.apache.shenyu.plugin.sign.api;
import org.apache.shenyu.common.utils.SignUtils;
+import java.util.Comparator;
import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
/**
* The Sign plugin default signer.
@@ -29,13 +32,28 @@ public class DefaultSignProvider implements SignProvider {
/**
* acquired sign.
*
- * @param signKey sign key
- * @param jsonParams json params
- * @param queryParams url query params
+ * @param signKey sign key
+ * @param jsonParams json params
+ * @param queryParams url query params
* @return sign
*/
@Override
public String generateSign(final String signKey, final Map<String, String> jsonParams, final Map<String, String> queryParams) {
- return SignUtils.generateSign(signKey, jsonParams, queryParams);
+
+ final String jsonSign = Optional.ofNullable(jsonParams).map(e -> e.keySet().stream()
+ .sorted(Comparator.naturalOrder())
+ .map(key -> String.join("", key, jsonParams.get(key)))
+ .collect(Collectors.joining()).trim())
+ .orElse("");
+
+ final String querySign = Optional.ofNullable(queryParams).map(e -> e.keySet().stream()
+ .sorted(Comparator.naturalOrder())
+ .map(key -> String.join("", key, queryParams.get(key)))
+ .collect(Collectors.joining()).trim())
+ .orElse("");
+
+ final String data = String.join("", jsonSign, querySign);
+
+ return SignUtils.sign(SignUtils.SIGN_MD5, signKey, data).toUpperCase();
}
}
diff --git a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/service/DefaultSignService.java b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/service/DefaultSignService.java
index b5297943e..11762196d 100644
--- a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/service/DefaultSignService.java
+++ b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/service/DefaultSignService.java
@@ -25,10 +25,10 @@ import org.apache.shenyu.common.dto.AppAuthData;
import org.apache.shenyu.common.dto.AuthParamData;
import org.apache.shenyu.common.dto.AuthPathData;
import org.apache.shenyu.common.utils.DateUtils;
-import org.apache.shenyu.plugin.base.utils.PathMatchUtils;
-import org.apache.shenyu.common.utils.SignUtils;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.plugin.api.context.ShenyuContext;
import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
+import org.apache.shenyu.plugin.base.utils.PathMatchUtils;
import org.apache.shenyu.plugin.sign.api.ShenyuSignProviderWrap;
import org.apache.shenyu.plugin.sign.api.SignService;
import org.apache.shenyu.plugin.sign.api.VerifyResult;
@@ -151,7 +151,7 @@ public class DefaultSignService implements SignService {
final Map<String, Object> requestBody,
final Map<String, String> queryParams) {
- final String sign = ShenyuSignProviderWrap.generateSign(buildExtSignKey(appAuthData.getAppSecret(), signParameters), SignUtils.transStringMap(requestBody), queryParams);
+ final String sign = ShenyuSignProviderWrap.generateSign(buildExtSignKey(appAuthData.getAppSecret(), signParameters), MapUtils.transStringMap(requestBody), queryParams);
boolean result = Objects.equals(sign, signParameters.sign);
if (!result) {
LOG.error("the SignUtils generated signature value is:{},the accepted value is:{}", sign, signParameters.sign);
diff --git a/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/service/DefaultSignServiceTest.java b/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/service/DefaultSignServiceTest.java
index e71a9dfcd..3a14af378 100644
--- a/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/service/DefaultSignServiceTest.java
+++ b/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/service/DefaultSignServiceTest.java
@@ -25,6 +25,7 @@ import org.apache.shenyu.common.dto.AuthParamData;
import org.apache.shenyu.common.dto.AuthPathData;
import org.apache.shenyu.common.dto.PluginData;
import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.utils.MapUtils;
import org.apache.shenyu.common.utils.SignUtils;
import org.apache.shenyu.plugin.api.context.ShenyuContext;
import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
@@ -48,7 +49,10 @@ import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.server.ServerWebExchange;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
@@ -243,7 +247,7 @@ public final class DefaultSignServiceTest {
public void bodySign() {
Map<String, Object> requestBody = Maps.newHashMapWithExpectedSize(1);
requestBody.put("data", "data");
- this.passed.setSign(buildSign(this.secretKey, this.passed.getTimestamp(), this.passed.getPath(), SignUtils.transStringMap(requestBody), null));
+ this.passed.setSign(buildSign(this.secretKey, this.passed.getTimestamp(), this.passed.getPath(), MapUtils.transStringMap(requestBody), null));
this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
VerifyResult ret = this.signService.signVerify(this.exchange, requestBody, null);
assertEquals(ret, VerifyResult.success());
@@ -255,7 +259,7 @@ public final class DefaultSignServiceTest {
requestBody.put("data", "data");
Map<String, String> queryParams = Maps.newHashMapWithExpectedSize(1);
queryParams.put("data2", "data");
- this.passed.setSign(buildSign(this.secretKey, this.passed.getTimestamp(), this.passed.getPath(), SignUtils.transStringMap(requestBody), queryParams));
+ this.passed.setSign(buildSign(this.secretKey, this.passed.getTimestamp(), this.passed.getPath(), MapUtils.transStringMap(requestBody), queryParams));
this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
VerifyResult ret = this.signService.signVerify(this.exchange, requestBody, queryParams);
assertEquals(ret, VerifyResult.success());
@@ -267,7 +271,7 @@ public final class DefaultSignServiceTest {
requestBody.put("data", "data");
Map<String, String> queryParams = Maps.newHashMapWithExpectedSize(1);
queryParams.put("data", "data");
- this.passed.setSign(buildSign(this.secretKey, this.passed.getTimestamp(), this.passed.getPath(), SignUtils.transStringMap(requestBody), null));
+ this.passed.setSign(buildSign(this.secretKey, this.passed.getTimestamp(), this.passed.getPath(), MapUtils.transStringMap(requestBody), null));
this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
// Tamper with request body parameters
requestBody.put("data", "data2");
@@ -276,7 +280,21 @@ public final class DefaultSignServiceTest {
}
private String buildSign(final String signKey, final String timeStamp, final String path, final Map<String, String> jsonParams, final Map<String, String> queryParams) {
+
+ final String jsonSign = Optional.ofNullable(jsonParams).map(e -> e.keySet().stream()
+ .sorted(Comparator.naturalOrder())
+ .map(key -> String.join("", key, jsonParams.get(key)))
+ .collect(Collectors.joining()).trim())
+ .orElse("");
+
+ final String querySign = Optional.ofNullable(queryParams).map(e -> e.keySet().stream()
+ .sorted(Comparator.naturalOrder())
+ .map(key -> String.join("", key, queryParams.get(key)))
+ .collect(Collectors.joining()).trim())
+ .orElse("");
+
final String extSignKey = String.join("", Constants.PATH, path, Constants.TIMESTAMP, timeStamp, Constants.VERSION, "1.0.0", signKey);
- return SignUtils.generateSign(extSignKey, jsonParams, queryParams);
+ final String data = String.join("", jsonSign, querySign);
+ return SignUtils.sign(SignUtils.SIGN_MD5, extSignKey, data).toUpperCase();
}
}
diff --git a/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/sign/DefaultSignProviderTest.java b/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/sign/DefaultSignProviderTest.java
index e69b2c44d..62f024f2c 100644
--- a/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/sign/DefaultSignProviderTest.java
+++ b/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/sign/DefaultSignProviderTest.java
@@ -30,7 +30,8 @@ import org.springframework.context.ConfigurableApplicationContext;
import java.util.HashMap;
import java.util.Map;
-import static org.junit.Assert.assertNotNull;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -53,8 +54,9 @@ public class DefaultSignProviderTest {
jsonParams.put("a", "1");
jsonParams.put("b", "2");
Map<String, String> queryParams = new HashMap<>();
- jsonParams.put("a", "1");
- jsonParams.put("b", "2");
- assertNotNull(ShenyuSignProviderWrap.generateSign("test", jsonParams, queryParams));
+ queryParams.put("a", "1");
+ queryParams.put("b", "2");
+ assertThat(ShenyuSignProviderWrap.generateSign("test", jsonParams, queryParams),
+ is("9DDBB668873D97C25904FD9D5D6314CD"));
}
}
diff --git a/shenyu-web/src/main/java/org/apache/shenyu/web/controller/LocalPluginController.java b/shenyu-web/src/main/java/org/apache/shenyu/web/controller/LocalPluginController.java
index 6e75463b3..5c68dcf9c 100644
--- a/shenyu-web/src/main/java/org/apache/shenyu/web/controller/LocalPluginController.java
+++ b/shenyu-web/src/main/java/org/apache/shenyu/web/controller/LocalPluginController.java
@@ -53,11 +53,11 @@ import java.util.stream.Collectors;
@RestController
@RequestMapping(value = "/shenyu", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public class LocalPluginController {
-
+
private static final Logger LOG = LoggerFactory.getLogger(LocalPluginController.class);
-
+
private final PluginDataSubscriber subscriber;
-
+
/**
* Instantiates a new Plugin controller.
*
@@ -66,7 +66,7 @@ public class LocalPluginController {
public LocalPluginController(final PluginDataSubscriber subscriber) {
this.subscriber = subscriber;
}
-
+
/**
* Clean all mono.
*
@@ -80,7 +80,7 @@ public class LocalPluginController {
subscriber.refreshRuleDataAll();
return Mono.just(Constants.SUCCESS);
}
-
+
/**
* Clean plugin mono.
*
@@ -101,7 +101,7 @@ public class LocalPluginController {
}
return Mono.just(Constants.SUCCESS);
}
-
+
/**
* Add plugin string.
*
@@ -317,7 +317,7 @@ public class LocalPluginController {
}
return Mono.just(JsonUtils.toJson(ruleDataList));
}
-
+
private SelectorData buildDefaultSelectorData(final SelectorData selectorData) {
if (StringUtils.isEmpty(selectorData.getId())) {
selectorData.setId(UUIDUtils.getInstance().generateShortUuid());
@@ -342,7 +342,7 @@ public class LocalPluginController {
}
return selectorData;
}
-
+
private RuleData buildDefaultRuleData(final RuleData ruleData) {
if (StringUtils.isEmpty(ruleData.getId())) {
ruleData.setId(UUIDUtils.getInstance().generateShortUuid());
@@ -364,22 +364,22 @@ public class LocalPluginController {
}
return ruleData;
}
-
+
/**
* The type Selector rule data.
*/
public static class SelectorRuleData {
-
+
private String pluginName;
-
+
private String selectorName;
-
+
private String selectorHandler;
-
+
private String ruleHandler;
-
+
private List<ConditionData> conditionDataList;
-
+
/**
* Gets plugin name.
*
@@ -388,7 +388,7 @@ public class LocalPluginController {
public String getPluginName() {
return pluginName;
}
-
+
/**
* Sets plugin name.
*
@@ -397,7 +397,7 @@ public class LocalPluginController {
public void setPluginName(final String pluginName) {
this.pluginName = pluginName;
}
-
+
/**
* Gets selector name.
*
@@ -406,7 +406,7 @@ public class LocalPluginController {
public String getSelectorName() {
return selectorName;
}
-
+
/**
* Sets selector name.
*
@@ -415,7 +415,7 @@ public class LocalPluginController {
public void setSelectorName(final String selectorName) {
this.selectorName = selectorName;
}
-
+
/**
* Gets selector handler.
*
@@ -424,7 +424,7 @@ public class LocalPluginController {
public String getSelectorHandler() {
return selectorHandler;
}
-
+
/**
* Sets selector handler.
*
@@ -433,7 +433,7 @@ public class LocalPluginController {
public void setSelectorHandler(final String selectorHandler) {
this.selectorHandler = selectorHandler;
}
-
+
/**
* Gets rule handler.
*
@@ -442,7 +442,7 @@ public class LocalPluginController {
public String getRuleHandler() {
return ruleHandler;
}
-
+
/**
* Sets rule handler.
*
@@ -451,7 +451,7 @@ public class LocalPluginController {
public void setRuleHandler(final String ruleHandler) {
this.ruleHandler = ruleHandler;
}
-
+
/**
* Gets condition data list.
*
@@ -460,7 +460,7 @@ public class LocalPluginController {
public List<ConditionData> getConditionDataList() {
return conditionDataList;
}
-
+
/**
* Sets condition data list.
*
@@ -470,24 +470,24 @@ public class LocalPluginController {
this.conditionDataList = conditionDataList;
}
}
-
+
/**
* The type Selector rules data.
*/
public static class SelectorRulesData {
-
+
private String pluginName;
-
+
private String selectorName;
-
+
private Integer matchMode;
-
+
private String selectorHandler;
-
+
private List<ConditionData> conditionDataList;
-
+
private List<RuleLocalData> ruleDataList;
-
+
/**
* Gets plugin name.
*
@@ -496,7 +496,7 @@ public class LocalPluginController {
public String getPluginName() {
return pluginName;
}
-
+
/**
* Sets plugin name.
*
@@ -505,7 +505,7 @@ public class LocalPluginController {
public void setPluginName(final String pluginName) {
this.pluginName = pluginName;
}
-
+
/**
* Gets selector name.
*
@@ -514,7 +514,7 @@ public class LocalPluginController {
public String getSelectorName() {
return selectorName;
}
-
+
/**
* Sets selector name.
*
@@ -523,7 +523,7 @@ public class LocalPluginController {
public void setSelectorName(final String selectorName) {
this.selectorName = selectorName;
}
-
+
/**
* Gets selector handler.
*
@@ -532,7 +532,7 @@ public class LocalPluginController {
public String getSelectorHandler() {
return selectorHandler;
}
-
+
/**
* Sets selector handler.
*
@@ -541,7 +541,7 @@ public class LocalPluginController {
public void setSelectorHandler(final String selectorHandler) {
this.selectorHandler = selectorHandler;
}
-
+
/**
* Gets match mode.
*
@@ -550,7 +550,7 @@ public class LocalPluginController {
public Integer getMatchMode() {
return matchMode;
}
-
+
/**
* Sets match mode.
*
@@ -559,7 +559,7 @@ public class LocalPluginController {
public void setMatchMode(final Integer matchMode) {
this.matchMode = matchMode;
}
-
+
/**
* Gets condition data list.
*
@@ -568,7 +568,7 @@ public class LocalPluginController {
public List<ConditionData> getConditionDataList() {
return conditionDataList;
}
-
+
/**
* Sets condition data list.
*
@@ -577,7 +577,7 @@ public class LocalPluginController {
public void setConditionDataList(final List<ConditionData> conditionDataList) {
this.conditionDataList = conditionDataList;
}
-
+
/**
* Gets rule data list.
*
@@ -586,7 +586,7 @@ public class LocalPluginController {
public List<RuleLocalData> getRuleDataList() {
return ruleDataList;
}
-
+
/**
* Sets rule data list.
*
@@ -595,22 +595,22 @@ public class LocalPluginController {
public void setRuleDataList(final List<RuleLocalData> ruleDataList) {
this.ruleDataList = ruleDataList;
}
-
+
}
-
+
/**
* The type Rule data dto.
*/
public static class RuleLocalData {
-
+
private String ruleName;
-
+
private String ruleHandler;
-
+
private Integer matchMode;
-
+
private List<ConditionData> conditionDataList;
-
+
/**
* Gets rule name.
*
@@ -619,7 +619,7 @@ public class LocalPluginController {
public String getRuleName() {
return ruleName;
}
-
+
/**
* Sets rule name.
*
@@ -628,7 +628,7 @@ public class LocalPluginController {
public void setRuleName(final String ruleName) {
this.ruleName = ruleName;
}
-
+
/**
* Gets rule handler.
*
@@ -637,7 +637,7 @@ public class LocalPluginController {
public String getRuleHandler() {
return ruleHandler;
}
-
+
/**
* Sets rule handler.
*
@@ -646,7 +646,7 @@ public class LocalPluginController {
public void setRuleHandler(final String ruleHandler) {
this.ruleHandler = ruleHandler;
}
-
+
/**
* Gets match mode.
*
@@ -655,7 +655,7 @@ public class LocalPluginController {
public Integer getMatchMode() {
return matchMode;
}
-
+
/**
* Sets match mode.
*
@@ -664,7 +664,7 @@ public class LocalPluginController {
public void setMatchMode(final Integer matchMode) {
this.matchMode = matchMode;
}
-
+
/**
* Gets condition data list.
*
@@ -673,7 +673,7 @@ public class LocalPluginController {
public List<ConditionData> getConditionDataList() {
return conditionDataList;
}
-
+
/**
* Sets condition data list.
*