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

xiaoyu 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 f6d40a5b6 [type: refactor] refactor DefaultSignService#signVerify 
(#4217)
f6d40a5b6 is described below

commit f6d40a5b61168fa8a4a738f8ea681d41acb1d4a2
Author: 愿凌飞 <[email protected]>
AuthorDate: Wed Nov 30 10:49:39 2022 +0800

    [type: refactor] refactor DefaultSignService#signVerify (#4217)
    
    Co-authored-by: likeguo <[email protected]>
    Co-authored-by: xiaoyu <[email protected]>
---
 .../org/apache/shenyu/plugin/sign/SignPlugin.java  |  14 +-
 .../apache/shenyu/plugin/sign/api/SignService.java |  13 +-
 .../shenyu/plugin/sign/api/VerifyResult.java       |  97 ++++++++++
 .../shenyu/plugin/sign/api/VerifySupplier.java     |  56 ++++++
 .../plugin/sign/service/DefaultSignService.java    | 200 +++++++++++++++------
 .../apache/shenyu/plugin/sign/SignPluginTest.java  |  10 +-
 .../sign/service/DefaultSignServiceTest.java       |  67 +++----
 7 files changed, 349 insertions(+), 108 deletions(-)

diff --git 
a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/SignPlugin.java
 
b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/SignPlugin.java
index e76578685..f40247718 100644
--- 
a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/SignPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/SignPlugin.java
@@ -18,7 +18,6 @@
 package org.apache.shenyu.plugin.sign;
 
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.enums.PluginEnum;
@@ -36,6 +35,7 @@ import org.apache.shenyu.plugin.sign.api.SignService;
 import org.apache.shenyu.plugin.sign.decorator.SignRequestDecorator;
 import org.apache.shenyu.plugin.sign.handler.SignPluginDataHandler;
 import org.apache.shenyu.plugin.sign.handler.SignRuleHandler;
+import org.apache.shenyu.plugin.sign.api.VerifyResult;
 import org.springframework.http.ReactiveHttpOutputMessage;
 import org.springframework.http.codec.HttpMessageReader;
 import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
@@ -98,9 +98,9 @@ public class SignPlugin extends AbstractShenyuPlugin {
                         return 
chain.execute(exchange.mutate().request(decorator).build());
                     })).onErrorResume((Function<Throwable, Mono<Void>>) 
throwable -> ResponseUtils.release(outputMessage, throwable));
         }
-        Pair<Boolean, String> result = signService.signVerify(exchange);
-        if (Boolean.FALSE.equals(result.getLeft())) {
-            Object error = ShenyuResultWrap.error(exchange, 
ShenyuResultEnum.SIGN_IS_NOT_PASS.getCode(), result.getRight(), null);
+        VerifyResult result = signService.signVerify(exchange);
+        if (result.isFailed()) {
+            Object error = ShenyuResultWrap.error(exchange, 
ShenyuResultEnum.SIGN_IS_NOT_PASS.getCode(), result.getReason(), null);
             return WebFluxResultUtils.result(exchange, error);
         }
 
@@ -115,9 +115,9 @@ public class SignPlugin extends AbstractShenyuPlugin {
         // get post body
         Map<String, Object> requestBody = StringUtils.isBlank(originalBody) ? 
null : JsonUtils.jsonToMap(originalBody);
         Map<String, String> queryParamsSingleValueMap = 
queryParams.toSingleValueMap();
-        Pair<Boolean, String> result = signService.signVerify(exchange, 
requestBody, queryParamsSingleValueMap);
-        if (Boolean.FALSE.equals(result.getLeft())) {
-            Object error = ShenyuResultWrap.error(exchange, 
ShenyuResultEnum.SIGN_IS_NOT_PASS.getCode(), result.getRight(), null);
+        VerifyResult result = signService.signVerify(exchange, requestBody, 
queryParamsSingleValueMap);
+        if (result.isFailed()) {
+            Object error = ShenyuResultWrap.error(exchange, 
ShenyuResultEnum.SIGN_IS_NOT_PASS.getCode(), result.getReason(), null);
             return WebFluxResultUtils.result(exchange, error);
         }
         // return original data
diff --git 
a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/SignService.java
 
b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/SignService.java
index d7c0da3c6..660c47b22 100644
--- 
a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/SignService.java
+++ 
b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/SignService.java
@@ -17,7 +17,6 @@
 
 package org.apache.shenyu.plugin.sign.api;
 
-import org.apache.commons.lang3.tuple.Pair;
 import org.springframework.web.server.ServerWebExchange;
 
 import java.util.Map;
@@ -29,19 +28,21 @@ public interface SignService {
 
     /**
      * Sign verify pair.
-     * @param exchange   the exchange
+     *
+     * @param exchange    the exchange
      * @param requestBody the requestBody
-     * @param queryParams  url query params
+     * @param queryParams url query params
      * @return the pair
      */
-    Pair<Boolean, String> signVerify(ServerWebExchange exchange, Map<String, 
Object> requestBody, Map<String, String> queryParams);
+    VerifyResult signVerify(ServerWebExchange exchange, Map<String, Object> 
requestBody, Map<String, String> queryParams);
 
     /**
      * Sign verify pair.
-     * @param exchange   the exchange
+     *
+     * @param exchange the exchange
      * @return the pair
      */
-    default Pair<Boolean, String> signVerify(ServerWebExchange exchange) {
+    default VerifyResult signVerify(ServerWebExchange exchange) {
         return signVerify(exchange, null, null);
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/VerifyResult.java
 
b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/VerifyResult.java
new file mode 100644
index 000000000..fefcae8a8
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/VerifyResult.java
@@ -0,0 +1,97 @@
+/*
+ * 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.plugin.sign.api;
+
+import com.google.common.base.Objects;
+
+public final class VerifyResult {
+
+    private static final VerifyResult SUCCESS = new VerifyResult(true, 
"success");
+
+    private final boolean success;
+
+    private final String reason;
+
+    private VerifyResult(final boolean success, final String reason) {
+        this.success = success;
+        this.reason = reason;
+    }
+
+    /**
+     * Get the reason for the failure.
+     *
+     * @return reason
+     */
+    public String getReason() {
+        return reason;
+    }
+
+    /**
+     * success or not.
+     *
+     * @return true or false
+     */
+    public boolean isSuccess() {
+        return success;
+    }
+
+    /**
+     * Failure or not.
+     *
+     * @return true or false
+     */
+    public boolean isFailed() {
+        return !success;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+        VerifyResult result = (VerifyResult) o;
+        return success == result.success && Objects.equal(reason, 
result.reason);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(success, reason);
+    }
+
+    /**
+     * Generate failed verifyResult.
+     *
+     * @param reason The reason for the failure
+     * @return verifyResult
+     */
+    public static VerifyResult fail(final String reason) {
+        return new VerifyResult(false, reason);
+    }
+
+    /**
+     * Generate successful verifyResult.
+     *
+     * @return verifyResult
+     */
+    public static VerifyResult success() {
+        return SUCCESS;
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/VerifySupplier.java
 
b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/VerifySupplier.java
new file mode 100644
index 000000000..8331d1435
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-sign/src/main/java/org/apache/shenyu/plugin/sign/api/VerifySupplier.java
@@ -0,0 +1,56 @@
+/*
+ * 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.plugin.sign.api;
+
+import java.util.Objects;
+
+@FunctionalInterface
+public interface VerifySupplier {
+
+    /**
+     * Verifies and gets a result.
+     * @return result
+     */
+    VerifyResult verify();
+
+    /**
+     * Returns a composed verifySupplier that represents a short-circuiting 
logical AND of this verifySupplier and another. When evaluating the composed 
verifySupplier,
+     * if this verifyResult is failed, then the other verifySupplier is not 
evaluated.
+     * @param other a verifySupplier that will be logically-ANDed with this 
verifySupplier
+     * @return a composed verifySupplier
+     */
+    default VerifySupplier and(VerifySupplier other) {
+        Objects.requireNonNull(other);
+        return () -> {
+            VerifyResult verifyResult = verify();
+            if (verifyResult.isFailed()) {
+                return verifyResult;
+            }
+            return other.verify();
+        };
+    }
+
+    /**
+     * Returns itself, this mainly helps to write smooth code.
+     * @param verifySupplier verifySupplier
+     * @return verifySupplier
+     */
+    static VerifySupplier apply(VerifySupplier verifySupplier) {
+        return verifySupplier;
+    }
+}
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 d8a3c99c7..b5297943e 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
@@ -18,8 +18,8 @@
 package org.apache.shenyu.plugin.sign.service;
 
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.BooleanUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.AppAuthData;
 import org.apache.shenyu.common.dto.AuthParamData;
@@ -31,6 +31,8 @@ import org.apache.shenyu.plugin.api.context.ShenyuContext;
 import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
 import org.apache.shenyu.plugin.sign.api.ShenyuSignProviderWrap;
 import org.apache.shenyu.plugin.sign.api.SignService;
+import org.apache.shenyu.plugin.sign.api.VerifyResult;
+import org.apache.shenyu.plugin.sign.api.VerifySupplier;
 import org.apache.shenyu.plugin.sign.cache.SignAuthDataCache;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -41,6 +43,7 @@ import java.time.LocalDateTime;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 
 /**
  * The type Default sign service.
@@ -53,79 +56,160 @@ public class DefaultSignService implements SignService {
     private int delay;
 
     @Override
-    public Pair<Boolean, String> signVerify(final ServerWebExchange exchange, 
final Map<String, Object> requestBody, final Map<String, String> queryParams) {
+    public VerifyResult signVerify(final ServerWebExchange exchange, final 
Map<String, Object> requestBody, final Map<String, String> queryParams) {
         final ShenyuContext shenyuContext = 
exchange.getAttribute(Constants.CONTEXT);
         assert shenyuContext != null;
-        return verify(shenyuContext, exchange, requestBody, queryParams);
+        return verify(buildSignParameters(shenyuContext), exchange, 
requestBody, queryParams);
     }
 
-    private Pair<Boolean, String> verify(final ShenyuContext shenyuContext, 
final ServerWebExchange exchange, final Map<String, Object> requestBody, final 
Map<String, String> queryParams) {
-        if (StringUtils.isBlank(shenyuContext.getAppKey())
-                || StringUtils.isBlank(shenyuContext.getSign())
-                || StringUtils.isBlank(shenyuContext.getTimestamp())) {
-            LOG.error("sign parameters are incomplete,{}", shenyuContext);
-            return Pair.of(Boolean.FALSE, Constants.SIGN_PARAMS_ERROR);
+    private SignParameters buildSignParameters(final ShenyuContext 
shenyuContext) {
+        return new SignParameters(
+                shenyuContext.getAppKey(),
+                shenyuContext.getTimestamp(),
+                shenyuContext.getSign(),
+                shenyuContext.getPath(),
+                shenyuContext.getRealUrl(),
+                shenyuContext.getContextPath());
+    }
+
+    private VerifyResult verify(final SignParameters signParameters, final 
ServerWebExchange exchange, final Map<String, Object> requestBody, final 
Map<String, String> queryParams) {
+
+        final AppAuthData appAuthData = 
Optional.ofNullable(signParameters.appKey)
+                .map(key -> 
SignAuthDataCache.getInstance().obtainAuthData(key))
+                .orElse(null);
+
+        return VerifySupplier
+                .apply(() -> verifySignParameters(signParameters))
+                .and(() -> verifyExpires(signParameters))
+                .and(() -> verifyAuthConfig(appAuthData, signParameters))
+                .and(() -> verifyPath(appAuthData, signParameters))
+                .and(() -> verifySign(signParameters, appAuthData, exchange, 
requestBody, queryParams)).verify();
+    }
+
+    private VerifyResult verifyPath(final AppAuthData appAuthData, final 
SignParameters signParameters) {
+        if (BooleanUtils.isNotTrue(appAuthData.getOpen())) {
+            return VerifyResult.success();
+        }
+
+        List<AuthPathData> pathDataList = appAuthData.getPathDataList();
+        if (CollectionUtils.isEmpty(pathDataList)) {
+            LOG.error("You have not configured the sign path:{}", 
signParameters.appKey);
+            return VerifyResult.fail(Constants.SIGN_PATH_NOT_EXIST);
+        }
+
+        boolean match = pathDataList.stream().filter(AuthPathData::getEnabled)
+                .anyMatch(e -> PathMatchUtils.match(e.getPath(), 
signParameters.path));
+        if (!match) {
+            LOG.error("You have not configured the sign path:{},{}", 
signParameters.appKey, signParameters.realUrl);
+            return VerifyResult.fail(Constants.SIGN_PATH_NOT_EXIST);
         }
-        final LocalDateTime start = 
DateUtils.formatLocalDateTimeFromTimestampBySystemTimezone(Long.parseLong(shenyuContext.getTimestamp()));
+        return VerifyResult.success();
+    }
+
+    private VerifyResult verifyAuthConfig(final AppAuthData appAuthData, final 
SignParameters signParameters) {
+        if (Objects.isNull(appAuthData) || 
BooleanUtils.isFalse(appAuthData.getEnabled())) {
+            LOG.error("sign APP_KEY does not exist or has been disabled,{}", 
signParameters.appKey);
+            return VerifyResult.fail(Constants.SIGN_APP_KEY_IS_NOT_EXIST);
+        }
+        return VerifyResult.success();
+    }
+
+    private VerifyResult verifySignParameters(final SignParameters 
signParameters) {
+        boolean success = StringUtils.isNoneBlank(signParameters.appKey)
+                && StringUtils.isNoneBlank(signParameters.timestamp)
+                && StringUtils.isNoneBlank(signParameters.sign);
+        if (success) {
+            return VerifyResult.success();
+        }
+        LOG.error("sign parameters are incomplete,{}", signParameters);
+        return VerifyResult.fail(Constants.SIGN_PARAMS_ERROR);
+    }
+
+    private VerifyResult verifyExpires(final SignParameters signParameters) {
+        final LocalDateTime start = 
DateUtils.formatLocalDateTimeFromTimestampBySystemTimezone(Long.parseLong(signParameters.timestamp));
         final LocalDateTime now = LocalDateTime.now();
         final long between = DateUtils.acquireMinutesBetween(start, now);
-        if (between > delay || -between > delay) {
-            return Pair.of(Boolean.FALSE, 
String.format(ShenyuResultEnum.SIGN_TIME_IS_TIMEOUT.getMsg(), delay));
+        if (Math.abs(between) <= delay) {
+            return VerifyResult.success();
         }
-
-        return sign(shenyuContext, exchange, requestBody, queryParams);
+        return 
VerifyResult.fail(String.format(ShenyuResultEnum.SIGN_TIME_IS_TIMEOUT.getMsg(), 
delay));
     }
 
     /**
-     verify sign .
+     * verify sign .
      *
-     * @param shenyuContext {@linkplain ShenyuContext}
-     * @param exchange exchange
-     * @param requestBody  the request body
-     * @param queryParams  url query params
-     * @return result : True is pass, False is not pass.
+     * @param signParameters signParameters
+     * @param appAuthData    appAuthData
+     * @param exchange       exchange
+     * @param requestBody    the request body
+     * @param queryParams    url query params
+     * @return verifyResult verifyResult
      */
-    private Pair<Boolean, String> sign(final ShenyuContext shenyuContext, 
final ServerWebExchange exchange, final Map<String, Object> requestBody, final 
Map<String, String> queryParams) {
-        final AppAuthData appAuthData = 
SignAuthDataCache.getInstance().obtainAuthData(shenyuContext.getAppKey());
-        if (Objects.isNull(appAuthData) || 
Boolean.FALSE.equals(appAuthData.getEnabled())) {
-            LOG.error("sign APP_kEY does not exist or has been disabled,{}", 
shenyuContext.getAppKey());
-            return Pair.of(Boolean.FALSE, Constants.SIGN_APP_KEY_IS_NOT_EXIST);
-        }
-        if (Boolean.TRUE.equals(appAuthData.getOpen())) {
-            List<AuthPathData> pathDataList = appAuthData.getPathDataList();
-            if (CollectionUtils.isEmpty(pathDataList)) {
-                LOG.error("You have not configured the sign path:{}", 
shenyuContext.getAppKey());
-                return Pair.of(Boolean.FALSE, Constants.SIGN_PATH_NOT_EXIST);
-            }
-
-            boolean match = 
pathDataList.stream().filter(AuthPathData::getEnabled)
-                    .anyMatch(e -> PathMatchUtils.match(e.getPath(), 
shenyuContext.getPath()));
-            if (!match) {
-                LOG.error("You have not configured the sign path:{},{}", 
shenyuContext.getAppKey(), shenyuContext.getRealUrl());
-                return Pair.of(Boolean.FALSE, Constants.SIGN_PATH_NOT_EXIST);
-            }
-        }
-        final String sign = 
ShenyuSignProviderWrap.generateSign(buildExtSignKey(appAuthData.getAppSecret(), 
shenyuContext), SignUtils.transStringMap(requestBody), queryParams);
-        boolean result = Objects.equals(sign, shenyuContext.getSign());
+    private VerifyResult verifySign(final SignParameters signParameters,
+                                    final AppAuthData appAuthData,
+                                    final ServerWebExchange exchange,
+                                    final Map<String, Object> requestBody,
+                                    final Map<String, String> queryParams) {
+
+        final String sign = 
ShenyuSignProviderWrap.generateSign(buildExtSignKey(appAuthData.getAppSecret(), 
signParameters), SignUtils.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, shenyuContext.getSign());
-            return Pair.of(Boolean.FALSE, Constants.SIGN_VALUE_IS_ERROR);
-        } else {
-            List<AuthParamData> paramDataList = appAuthData.getParamDataList();
-            if (CollectionUtils.isEmpty(paramDataList)) {
-                return Pair.of(Boolean.TRUE, "");
-            }
-            paramDataList.stream().filter(p ->
-                    ("/" + 
p.getAppName()).equals(shenyuContext.getContextPath()))
-                    .map(AuthParamData::getAppParam)
-                    .filter(StringUtils::isNoneBlank).findFirst()
-                    .ifPresent(param -> 
exchange.getRequest().mutate().headers(httpHeaders -> 
httpHeaders.set(Constants.APP_PARAM, param)).build()
-            );
+            LOG.error("the SignUtils generated signature value is:{},the 
accepted value is:{}", sign, signParameters.sign);
+            return VerifyResult.fail(Constants.SIGN_VALUE_IS_ERROR);
+        }
+
+        List<AuthParamData> paramDataList = appAuthData.getParamDataList();
+        if (CollectionUtils.isEmpty(paramDataList)) {
+            return VerifyResult.success();
         }
-        return Pair.of(Boolean.TRUE, "");
+        paramDataList.stream().filter(p ->
+                ("/" + p.getAppName()).equals(signParameters.contextPath))
+                .map(AuthParamData::getAppParam)
+                .filter(StringUtils::isNoneBlank).findFirst()
+                .ifPresent(param -> 
exchange.getRequest().mutate().headers(httpHeaders -> 
httpHeaders.set(Constants.APP_PARAM, param)).build());
+
+        return VerifyResult.success();
+    }
+
+    private String buildExtSignKey(final String signKey, final SignParameters 
signParameters) {
+        return String.join("", Constants.PATH, signParameters.path, 
Constants.TIMESTAMP, signParameters.timestamp, Constants.VERSION, "1.0.0", 
signKey);
     }
 
-    private String buildExtSignKey(final String signKey, final ShenyuContext 
shenyuContext) {
-        return String.join("", Constants.PATH, shenyuContext.getPath(), 
Constants.TIMESTAMP, shenyuContext.getTimestamp(), Constants.VERSION, "1.0.0", 
signKey);
+    private static final class SignParameters {
+
+        private final String appKey;
+
+        private final String timestamp;
+
+        private final String sign;
+
+        private final String path;
+
+        private final String realUrl;
+
+        private final String contextPath;
+
+        private SignParameters(final String appKey,
+                               final String timestamp,
+                               final String sign,
+                               final String path,
+                               final String realUrl,
+                               final String contextPath) {
+
+            this.appKey = appKey;
+            this.timestamp = timestamp;
+            this.sign = sign;
+            this.path = path;
+            this.realUrl = realUrl;
+            this.contextPath = contextPath;
+        }
+
+        @Override
+        public String toString() {
+            return "SignParameters{" + "appKey='" + appKey
+                    + '\'' + ", timestamp='" + timestamp
+                    + '\'' + ", sign='" + sign + '\''
+                    + '}';
+        }
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/SignPluginTest.java
 
b/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/SignPluginTest.java
index 1bb438c01..5b47d4418 100644
--- 
a/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/SignPluginTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-sign/src/test/java/org/apache/shenyu/plugin/sign/SignPluginTest.java
@@ -18,7 +18,6 @@
 package org.apache.shenyu.plugin.sign;
 
 import com.google.common.collect.Maps;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.enums.PluginEnum;
@@ -29,6 +28,7 @@ import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.apache.shenyu.plugin.sign.api.SignService;
 import org.apache.shenyu.plugin.sign.handler.SignPluginDataHandler;
 import org.apache.shenyu.plugin.sign.handler.SignRuleHandler;
+import org.apache.shenyu.plugin.sign.api.VerifyResult;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -103,7 +103,7 @@ public final class SignPluginTest {
     public void testSignPluginSimple() {
         this.exchange = 
MockServerWebExchange.from(MockServerHttpRequest.get("localhost").build());
 
-        when(signService.signVerify(exchange)).thenReturn(Pair.of(true, ""));
+        
when(signService.signVerify(exchange)).thenReturn(VerifyResult.success());
         RuleData data = mock(RuleData.class);
         SelectorData selectorData = mock(SelectorData.class);
         when(chain.execute(exchange)).thenReturn(Mono.empty());
@@ -114,7 +114,7 @@ public final class SignPluginTest {
     public void testSignPluginSimple2() {
         this.exchange = 
MockServerWebExchange.from(MockServerHttpRequest.get("localhost").build());
 
-        when(signService.signVerify(exchange)).thenReturn(Pair.of(false, ""));
+        
when(signService.signVerify(exchange)).thenReturn(VerifyResult.fail(""));
         RuleData data = mock(RuleData.class);
         SelectorData selectorData = mock(SelectorData.class);
         when(chain.execute(exchange)).thenReturn(Mono.empty());
@@ -133,7 +133,7 @@ public final class SignPluginTest {
         Map<String, Object> requestBody = Maps.newHashMapWithExpectedSize(1);
         requestBody.put("data", "3");
         Map<String, String> queryParams = 
exchange.getRequest().getQueryParams().toSingleValueMap();
-        when(signService.signVerify(exchange, requestBody, 
queryParams)).thenReturn(Pair.of(true, ""));
+        when(signService.signVerify(exchange, requestBody, 
queryParams)).thenReturn(VerifyResult.success());
         when(this.chain.execute(any())).thenReturn(Mono.empty());
         SelectorData selectorData = mock(SelectorData.class);
         signPluginDataHandler.handlerRule(ruleData);
@@ -154,7 +154,7 @@ public final class SignPluginTest {
         Map<String, Object> requestBody = Maps.newHashMapWithExpectedSize(1);
         requestBody.put("data", "4");
         Map<String, String> queryParams = 
exchange.getRequest().getQueryParams().toSingleValueMap();
-        when(signService.signVerify(exchange, requestBody, 
queryParams)).thenReturn(Pair.of(false, ""));
+        when(signService.signVerify(exchange, requestBody, 
queryParams)).thenReturn(VerifyResult.fail(""));
         when(this.chain.execute(any())).thenReturn(Mono.empty());
         SelectorData selectorData = mock(SelectorData.class);
         signPluginDataHandler.handlerRule(ruleData);
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 6f766717f..e71a9dfcd 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
@@ -19,7 +19,6 @@ package org.apache.shenyu.plugin.sign.service;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import org.apache.commons.lang3.tuple.Pair;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.AppAuthData;
 import org.apache.shenyu.common.dto.AuthParamData;
@@ -34,6 +33,7 @@ import org.apache.shenyu.plugin.base.cache.BaseDataCache;
 import org.apache.shenyu.plugin.sign.api.DefaultSignProvider;
 import org.apache.shenyu.plugin.sign.api.SignProvider;
 import org.apache.shenyu.plugin.sign.api.SignService;
+import org.apache.shenyu.plugin.sign.api.VerifyResult;
 import org.apache.shenyu.plugin.sign.cache.SignAuthDataCache;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -121,8 +121,8 @@ public final class DefaultSignServiceTest {
     public void normalTest() {
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(true, ""));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, VerifyResult.success());
     }
 
     @Test
@@ -130,17 +130,20 @@ public final class DefaultSignServiceTest {
         this.passed.setTimestamp(null);
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(false, Constants.SIGN_PARAMS_ERROR));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, VerifyResult.fail(Constants.SIGN_PARAMS_ERROR));
     }
 
     @Test
     public void nullSignTest() {
         this.passed.setSign(null);
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
+        AppAuthData authData = 
SignAuthDataCache.getInstance().obtainAuthData(appKey);
+        authData.setPathDataList(Collections.emptyList());
+        SignAuthDataCache.getInstance().cacheAuthData(authData);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(false, Constants.SIGN_PARAMS_ERROR));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, VerifyResult.fail(Constants.SIGN_PARAMS_ERROR));
     }
 
     @Test
@@ -148,19 +151,19 @@ public final class DefaultSignServiceTest {
         this.passed.setAppKey(null);
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(false, Constants.SIGN_PARAMS_ERROR));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, VerifyResult.fail(Constants.SIGN_PARAMS_ERROR));
     }
 
     @Test
     public void overdueTest() {
-        long errorTimestamp = Long.parseLong(this.passed.getTimestamp()) - 
(long) ((delay + 1) * 1000 * 60);
+        long errorTimestamp = Long.parseLong(this.passed.getTimestamp()) - 
((long) (delay + 1) * 1000 * 60);
         this.passed.setTimestamp(Long.toString(errorTimestamp));
         this.passed.setSign(buildSign(this.secretKey, 
this.passed.getTimestamp(), this.passed.getPath(), null, null));
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(false, 
String.format(ShenyuResultEnum.SIGN_TIME_IS_TIMEOUT.getMsg(), delay)));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, 
VerifyResult.fail(String.format(ShenyuResultEnum.SIGN_TIME_IS_TIMEOUT.getMsg(), 
delay)));
     }
 
     @Test
@@ -168,8 +171,8 @@ public final class DefaultSignServiceTest {
         this.passed.setAppKey("errorKey");
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(false, Constants.SIGN_APP_KEY_IS_NOT_EXIST));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, 
VerifyResult.fail(Constants.SIGN_APP_KEY_IS_NOT_EXIST));
     }
 
     @Test
@@ -179,8 +182,8 @@ public final class DefaultSignServiceTest {
         authData.setPathDataList(Collections.emptyList());
         SignAuthDataCache.getInstance().cacheAuthData(authData);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(false, Constants.SIGN_PATH_NOT_EXIST));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, VerifyResult.fail(Constants.SIGN_PATH_NOT_EXIST));
     }
 
     @Test
@@ -193,8 +196,8 @@ public final class DefaultSignServiceTest {
         authData.setParamDataList(Collections.singletonList(authParamData));
         SignAuthDataCache.getInstance().cacheAuthData(authData);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(true, ""));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, VerifyResult.success());
     }
 
     @Test
@@ -203,8 +206,8 @@ public final class DefaultSignServiceTest {
         AppAuthData authData = 
SignAuthDataCache.getInstance().obtainAuthData(appKey);
         SignAuthDataCache.getInstance().cacheAuthData(authData);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(true, ""));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, VerifyResult.success());
     }
 
     @Test
@@ -213,8 +216,8 @@ public final class DefaultSignServiceTest {
         this.passed.setSign(buildSign(this.secretKey, 
this.passed.getTimestamp(), this.passed.getPath(), null, null));
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(false, Constants.SIGN_PATH_NOT_EXIST));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, VerifyResult.fail(Constants.SIGN_PATH_NOT_EXIST));
     }
 
     @Test
@@ -222,8 +225,8 @@ public final class DefaultSignServiceTest {
         this.passed.setSign("errorSign");
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
 
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange);
-        assertEquals(ret, Pair.of(false, Constants.SIGN_VALUE_IS_ERROR));
+        VerifyResult ret = this.signService.signVerify(this.exchange);
+        assertEquals(ret, VerifyResult.fail(Constants.SIGN_VALUE_IS_ERROR));
     }
 
     @Test
@@ -232,8 +235,8 @@ public final class DefaultSignServiceTest {
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
         Map<String, Object> requestBody = Maps.newHashMapWithExpectedSize(1);
         requestBody.put("data", "data");
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange, 
requestBody, null);
-        assertEquals(ret, Pair.of(false, Constants.SIGN_VALUE_IS_ERROR));
+        VerifyResult ret = this.signService.signVerify(this.exchange, 
requestBody, null);
+        assertEquals(ret, VerifyResult.fail(Constants.SIGN_VALUE_IS_ERROR));
     }
 
     @Test
@@ -242,8 +245,8 @@ public final class DefaultSignServiceTest {
         requestBody.put("data", "data");
         this.passed.setSign(buildSign(this.secretKey, 
this.passed.getTimestamp(), this.passed.getPath(), 
SignUtils.transStringMap(requestBody), null));
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange, 
requestBody, null);
-        assertEquals(ret, Pair.of(true, ""));
+        VerifyResult ret = this.signService.signVerify(this.exchange, 
requestBody, null);
+        assertEquals(ret, VerifyResult.success());
     }
 
     @Test
@@ -254,8 +257,8 @@ public final class DefaultSignServiceTest {
         queryParams.put("data2", "data");
         this.passed.setSign(buildSign(this.secretKey, 
this.passed.getTimestamp(), this.passed.getPath(), 
SignUtils.transStringMap(requestBody), queryParams));
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange, 
requestBody, queryParams);
-        assertEquals(ret, Pair.of(true, ""));
+        VerifyResult ret = this.signService.signVerify(this.exchange, 
requestBody, queryParams);
+        assertEquals(ret, VerifyResult.success());
     }
 
     @Test
@@ -268,8 +271,8 @@ public final class DefaultSignServiceTest {
         this.exchange.getAttributes().put(Constants.CONTEXT, this.passed);
         // Tamper with request body parameters
         requestBody.put("data", "data2");
-        Pair<Boolean, String> ret = this.signService.signVerify(this.exchange, 
requestBody, queryParams);
-        assertEquals(ret, Pair.of(false, Constants.SIGN_VALUE_IS_ERROR));
+        VerifyResult ret = this.signService.signVerify(this.exchange, 
requestBody, queryParams);
+        assertEquals(ret, VerifyResult.fail(Constants.SIGN_VALUE_IS_ERROR));
     }
 
     private String buildSign(final String signKey, final String timeStamp, 
final String path, final Map<String, String> jsonParams, final Map<String, 
String> queryParams) {


Reply via email to