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 08ff2aa4b [Task #3011]The JwtRuleHandle should be coustomerd (#4133)
08ff2aa4b is described below

commit 08ff2aa4b00c0f72d158a514a7859343630b56f7
Author: 愿凌飞 <[email protected]>
AuthorDate: Fri Nov 11 11:57:59 2022 +0800

    [Task #3011]The JwtRuleHandle should be coustomerd (#4133)
    
    * [Task #3011]The JwtRuleHandle should be coustomerd
    
    * fixed null exception by check
    
    * fixed null exception by check
    
    * refactor jwtRuleHandle
    
    * fixed ugly naming
    
    * [type:refactor] spi implement converter
    
    * [type:refactor] spi implement converter
    
    * [type:refactor] spi implement converter
    
    * [type:refactor] spi implement converter
    
    * [type:refactor] spi implement converter
    
    * [type:refactor] spi implement converter
    
    Co-authored-by: likeguo <[email protected]>
    Co-authored-by: moremind <[email protected]>
    Co-authored-by: moremind <[email protected]>
---
 .../org/apache/shenyu/plugin/jwt/JwtPlugin.java    | 110 ++++++------------
 .../plugin/jwt/handle/JwtPluginDataHandler.java    |  11 +-
 .../plugin/jwt/rule/DefaultJwtRuleHandle.java      |  30 ++---
 .../shenyu/plugin/jwt/rule/JwtRuleHandle.java      |  78 +++++++++++++
 .../jwt/strategy/DefaultJwtConvertStrategy.java    | 118 +++++++++++++++++++
 .../plugin/jwt/strategy/JwtConvertStrategy.java    |  47 ++++++++
 .../jwt/strategy/JwtConvertStrategyFactory.java    |  41 +++++++
 ...e.shenyu.plugin.jwt.strategy.JwtConvertStrategy |  17 +++
 .../apache/shenyu/plugin/jwt/JwtPluginTest.java    | 125 ++++++++++-----------
 .../jwt/handle/JwtPluginDataHandlerTest.java       |  22 +---
 .../plugin/jwt/rule/CustomJwtRuleHandle.java       |  42 +++++++
 .../shenyu/plugin/jwt/rule}/JwtRuleHandleTest.java |  40 +++----
 .../jwt/strategy/CustomJwtConvertStrategy.java     |  46 ++++++++
 .../strategy/DefaultJwtConvertStrategyTest.java    | 114 +++++++++++++++++++
 ...e.shenyu.plugin.jwt.strategy.JwtConvertStrategy |  17 +++
 15 files changed, 649 insertions(+), 209 deletions(-)

diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java
index 556ef355e..8968bb3a3 100644
--- 
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java
@@ -24,27 +24,27 @@ import io.jsonwebtoken.Jwts;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
-import org.apache.shenyu.common.dto.convert.rule.impl.JwtRuleHandle;
 import org.apache.shenyu.common.enums.PluginEnum;
-import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.Singleton;
 import org.apache.shenyu.plugin.api.ShenyuPluginChain;
 import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
 import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
 import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
-import org.apache.shenyu.common.utils.Singleton;
-import org.apache.shenyu.plugin.jwt.config.JwtConfig;
 import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
+import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
+import org.apache.shenyu.plugin.jwt.config.JwtConfig;
 import org.apache.shenyu.plugin.jwt.exception.ThrowingFunction;
+import org.apache.shenyu.plugin.jwt.handle.JwtPluginDataHandler;
+import org.apache.shenyu.plugin.jwt.rule.JwtRuleHandle;
+import org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategy;
+import org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategyFactory;
 import org.springframework.http.HttpHeaders;
-import org.springframework.http.server.reactive.ServerHttpRequest;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
 
 import java.nio.charset.StandardCharsets;
-import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Jwt Plugin.
@@ -70,15 +70,17 @@ public class JwtPlugin extends AbstractShenyuPlugin {
         // compatible processing
         String finalAuthorization = compatible(token, authorization);
         Map<String, Object> jwtBody = checkAuthorization(finalAuthorization, 
jwtConfig.getSecretKey());
-        if (Objects.nonNull(jwtBody)) {
-            JwtRuleHandle ruleHandle = 
GsonUtils.getInstance().fromJson(rule.getHandle(), JwtRuleHandle.class);
-            if (Objects.isNull(ruleHandle) || 
Objects.isNull(ruleHandle.getConverter())) {
-                return chain.execute(exchange);
-            }
-            return chain.execute(converter(exchange, jwtBody, 
ruleHandle.getConverter()));
+
+        if (Objects.isNull(jwtBody)) {
+            Object error = ShenyuResultWrap.error(exchange, 
ShenyuResultEnum.ERROR_TOKEN);
+            return WebFluxResultUtils.result(exchange, error);
         }
-        Object error = ShenyuResultWrap.error(exchange, 
ShenyuResultEnum.ERROR_TOKEN);
-        return WebFluxResultUtils.result(exchange, error);
+
+        if (Objects.isNull(rule) || Objects.isNull(rule.getHandle())) {
+            return chain.execute(exchange);
+        }
+
+        return chain.execute(executeRuleHandle(rule, exchange, jwtBody));
     }
 
     @Override
@@ -91,9 +93,21 @@ public class JwtPlugin extends AbstractShenyuPlugin {
         return PluginEnum.JWT.getCode();
     }
 
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    private ServerWebExchange executeRuleHandle(final RuleData ruleData, final 
ServerWebExchange exchange, final Map<String, Object> jwtBody) {
+        JwtRuleHandle jwtRuleHandle = 
JwtPluginDataHandler.CACHED_HANDLE.get().obtainHandle(CacheKeyUtils.INST.getKey(ruleData));
+        if (Objects.isNull(jwtRuleHandle)) {
+            return exchange;
+        }
+        JwtConvertStrategy convertStrategy = 
JwtConvertStrategyFactory.newInstance(jwtRuleHandle.getHandleType());
+
+        return convertStrategy.convert(jwtRuleHandle, exchange, jwtBody);
+    }
+
     /**
      * Both are compatible.
-     * @param token header of token
+     *
+     * @param token         header of token
      * @param authorization header of authorization
      * @return the authorization after processing
      */
@@ -115,8 +129,9 @@ public class JwtPlugin extends AbstractShenyuPlugin {
 
     /**
      * check Authorization.
+     *
      * @param authorization the authorization after processing
-     * @param secretKey secretKey of authorization
+     * @param secretKey     secretKey of authorization
      * @return Map
      */
     private Map<String, Object> checkAuthorization(final String authorization,
@@ -138,65 +153,4 @@ public class JwtPlugin extends AbstractShenyuPlugin {
         }
         return null;
     }
-
-    /**
-     * The parameters in token are converted to request header.
-     *
-     * @param exchange exchange
-     * @return ServerWebExchange exchange.
-     */
-    private ServerWebExchange converter(final ServerWebExchange exchange,
-                                        final Map<String, Object> jwtBody,
-                                        final List<JwtRuleHandle.Convert> 
converters) {
-        ServerHttpRequest modifiedRequest = 
exchange.getRequest().mutate().headers(httpHeaders -> 
this.addHeader(httpHeaders, jwtBody, converters)).build();
-
-        return exchange.mutate().request(modifiedRequest).build();
-    }
-
-    /**
-     * add header.
-     *
-     * @param headers headers
-     * @param body body
-     * @param converters converters
-     */
-    private void addHeader(final HttpHeaders headers,
-                           final Map<String, Object> body,
-                           final List<JwtRuleHandle.Convert> converters) {
-        for (JwtRuleHandle.Convert converter : converters) {
-            if (converter.getJwtVal().contains(".")) {
-                headers.add(converter.getHeaderVal(), parse(body, 
converter.getJwtVal().split("\\."), new AtomicInteger(0)));
-            } else {
-                headers.add(converter.getHeaderVal(), 
String.valueOf(body.get(converter.getJwtVal())));
-            }
-        }
-    }
-
-    /**
-     * Parsing multi-level tokens.
-     *
-     * @param body  token
-     * @param split jwt of key
-     * @param deep  level default 0
-     * @return token of val
-     */
-    private String parse(final Map<String, Object> body,
-                        final String[] split,
-                        final AtomicInteger deep) {
-        for (Map.Entry<String, Object> entry : body.entrySet()) {
-
-            if (deep.get() == split.length - 1) {
-                return String.valueOf(body.get(split[deep.get()]));
-            }
-
-            if (entry.getKey().equals(split[deep.get()])) {
-                if (entry.getValue() instanceof Map) {
-                    deep.incrementAndGet();
-                    return parse((Map<String, Object>) entry.getValue(), 
split, deep);
-                }
-            }
-        }
-        return String.valueOf(body.get(split[deep.get()]));
-    }
-
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandler.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandler.java
index 9c816e843..4536de053 100644
--- 
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandler.java
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandler.java
@@ -20,15 +20,15 @@ package org.apache.shenyu.plugin.jwt.handle;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.PluginData;
 import org.apache.shenyu.common.dto.RuleData;
-import org.apache.shenyu.common.dto.convert.rule.impl.JwtRuleHandle;
 import org.apache.shenyu.common.enums.PluginEnum;
 import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.common.utils.Singleton;
 import org.apache.shenyu.plugin.base.cache.CommonHandleCache;
 import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
-import org.apache.shenyu.common.utils.Singleton;
 import org.apache.shenyu.plugin.base.utils.BeanHolder;
 import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
 import org.apache.shenyu.plugin.jwt.config.JwtConfig;
+import org.apache.shenyu.plugin.jwt.rule.JwtRuleHandle;
 
 import java.util.Map;
 import java.util.Optional;
@@ -50,11 +50,12 @@ public class JwtPluginDataHandler implements 
PluginDataHandler {
         Singleton.INST.single(JwtConfig.class, jwtConfig);
     }
 
+    @SuppressWarnings("rawtypes")
     @Override
     public void handlerRule(final RuleData ruleData) {
-        Optional.ofNullable(ruleData.getHandle()).ifPresent(s -> {
-            JwtRuleHandle ruleHandle = GsonUtils.getInstance().fromJson(s, 
JwtRuleHandle.class);
-            
CACHED_HANDLE.get().cachedHandle(CacheKeyUtils.INST.getKey(ruleData), 
ruleHandle);
+        Optional.ofNullable(ruleData.getHandle()).ifPresent(ruleHandle -> {
+            JwtRuleHandle jwtRuleHandle = 
JwtRuleHandle.newInstance(ruleHandle);
+            
CACHED_HANDLE.get().cachedHandle(CacheKeyUtils.INST.getKey(ruleData), 
jwtRuleHandle);
         });
     }
 
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/JwtRuleHandle.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/rule/DefaultJwtRuleHandle.java
similarity index 83%
rename from 
shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/JwtRuleHandle.java
rename to 
shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/rule/DefaultJwtRuleHandle.java
index 442edf38f..bd63ba0f6 100644
--- 
a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/JwtRuleHandle.java
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/rule/DefaultJwtRuleHandle.java
@@ -15,39 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.common.dto.convert.rule.impl;
-
-import org.apache.shenyu.common.dto.convert.rule.RuleHandle;
+package org.apache.shenyu.plugin.jwt.rule;
 
 import java.util.List;
 
-/**
- * Jwt rule handle.
- */
-public class JwtRuleHandle implements RuleHandle {
+public class DefaultJwtRuleHandle extends JwtRuleHandle {
+
+    private static final long serialVersionUID = 7090772288389508730L;
 
-    /**
-     * converter, Jwt's body content is assigned to the header.
-     */
     private List<Convert> converter;
 
     /**
      * get converter.
-     * @return List
+     *
+     * @return converter
      */
     public List<Convert> getConverter() {
         return converter;
     }
 
-    @Override
-    public String toString() {
-        return "JwtRuleHandle{"
-                + "converter=" + converter.toString()
-                + '}';
-    }
-
     /**
      * set converter.
+     *
      * @param converter converter
      */
     public void setConverter(final List<Convert> converter) {
@@ -68,6 +57,7 @@ public class JwtRuleHandle implements RuleHandle {
 
         /**
          * get jwtVal.
+         *
          * @return jwtVal
          */
         public String getJwtVal() {
@@ -76,6 +66,7 @@ public class JwtRuleHandle implements RuleHandle {
 
         /**
          * set jwtVal.
+         *
          * @param jwtVal jwtVal
          */
         public void setJwtVal(final String jwtVal) {
@@ -84,6 +75,7 @@ public class JwtRuleHandle implements RuleHandle {
 
         /**
          * get headerVal.
+         *
          * @return headerVal
          */
         public String getHeaderVal() {
@@ -92,6 +84,7 @@ public class JwtRuleHandle implements RuleHandle {
 
         /**
          * set headerVal.
+         *
          * @param headerVal headerVal
          */
         public void setHeaderVal(final String headerVal) {
@@ -106,4 +99,5 @@ public class JwtRuleHandle implements RuleHandle {
                     + '}';
         }
     }
+
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/rule/JwtRuleHandle.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/rule/JwtRuleHandle.java
new file mode 100644
index 000000000..8dcb8bb2b
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/rule/JwtRuleHandle.java
@@ -0,0 +1,78 @@
+/*
+ * 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.jwt.rule;
+
+import org.apache.shenyu.common.dto.convert.rule.RuleHandle;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategy;
+import org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategyFactory;
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Jwt rule handle.
+ */
+
+public class JwtRuleHandle implements RuleHandle, Serializable {
+
+    private static final long serialVersionUID = -3023493891692468701L;
+
+    private static final String DEFAULT_JWT_CONVERTER = "default";
+
+    private String handleType;
+
+    /**
+     * get handleType.
+     *
+     * @return handleType
+     */
+    public String getHandleType() {
+        return handleType;
+    }
+
+    /**
+     * set handleType.
+     *
+     * @param handleType handleType
+     */
+    public void setHandleType(final String handleType) {
+        this.handleType = handleType;
+    }
+
+    /**
+     * new instance jwtRuleHandle.
+     *
+     * @param handleJson handleJson from rule
+     * @return jwtRuleHandle
+     */
+    @SuppressWarnings("rawtypes")
+    public static JwtRuleHandle newInstance(final String handleJson) {
+        if (Objects.isNull(handleJson)) {
+            return null;
+        }
+        Map<String, Object> handleMap = 
GsonUtils.getInstance().convertToMap(handleJson);
+        String handleType = null;
+        if (Objects.nonNull(handleMap)) {
+            handleType = handleMap.getOrDefault("handleType", 
DEFAULT_JWT_CONVERTER).toString();
+        }
+        JwtConvertStrategy convertStrategy = 
JwtConvertStrategyFactory.newInstance(handleType);
+        return convertStrategy.parseHandleJson(handleJson);
+    }
+
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtConvertStrategy.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtConvertStrategy.java
new file mode 100644
index 000000000..22fe03a01
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtConvertStrategy.java
@@ -0,0 +1,118 @@
+/*
+ * 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.jwt.strategy;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.plugin.jwt.rule.DefaultJwtRuleHandle;
+import org.apache.shenyu.spi.Join;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.web.server.ServerWebExchange;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@Join
+public class DefaultJwtConvertStrategy implements 
JwtConvertStrategy<DefaultJwtRuleHandle> {
+
+    @Override
+    public DefaultJwtRuleHandle parseHandleJson(final String handleJson) {
+        try {
+            return GsonUtils.getInstance().fromJson(handleJson, 
DefaultJwtRuleHandle.class);
+        } catch (Exception ignore) {
+            //ignore wrong json format or alert client
+            return null;
+        }
+    }
+
+    @Override
+    public ServerWebExchange convert(final DefaultJwtRuleHandle jwtRuleHandle, 
final ServerWebExchange exchange, final Map<String, Object> jwtBody) {
+        if (CollectionUtils.isEmpty(jwtRuleHandle.getConverter())) {
+            return exchange;
+        }
+
+        return convert(exchange, jwtBody, jwtRuleHandle.getConverter());
+    }
+
+    /**
+     * The parameters in token are converted to request header.
+     *
+     * @param exchange exchange
+     * @return ServerWebExchange exchange.
+     */
+    private ServerWebExchange convert(final ServerWebExchange exchange,
+                                      final Map<String, Object> jwtBody, final 
List<DefaultJwtRuleHandle.Convert> converters) {
+        ServerHttpRequest modifiedRequest = 
exchange.getRequest().mutate().headers(httpHeaders -> 
this.addHeader(httpHeaders, jwtBody, converters)).build();
+
+        return exchange.mutate().request(modifiedRequest).build();
+    }
+
+    /**
+     * add header.
+     *
+     * @param headers    headers
+     * @param body       body
+     * @param converters converters
+     */
+    private void addHeader(final HttpHeaders headers,
+                           final Map<String, Object> body,
+                           final List<DefaultJwtRuleHandle.Convert> 
converters) {
+        for (DefaultJwtRuleHandle.Convert converter : converters) {
+
+            if (StringUtils.isEmpty(converter.getHeaderVal()) || 
StringUtils.isEmpty(converter.getJwtVal())) {
+                continue;
+            }
+
+            if (converter.getJwtVal().contains(".")) {
+                headers.add(converter.getHeaderVal(), parse(body, 
converter.getJwtVal().split("\\."), new AtomicInteger(0)));
+            }
+            headers.add(converter.getHeaderVal(), 
String.valueOf(body.get(converter.getJwtVal())));
+
+        }
+    }
+
+    /**
+     * Parsing multi-level tokens.
+     *
+     * @param body  token
+     * @param split jwt of key
+     * @param deep  level default 0
+     * @return token of val
+     */
+    private String parse(final Map<String, Object> body,
+                         final String[] split,
+                         final AtomicInteger deep) {
+        for (Map.Entry<String, Object> entry : body.entrySet()) {
+
+            if (deep.get() == split.length - 1) {
+                return String.valueOf(body.get(split[deep.get()]));
+            }
+
+            if (entry.getKey().equals(split[deep.get()])) {
+                if (entry.getValue() instanceof Map) {
+                    deep.incrementAndGet();
+                    return parse((Map<String, Object>) entry.getValue(), 
split, deep);
+                }
+            }
+        }
+        return String.valueOf(body.get(split[deep.get()]));
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtConvertStrategy.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtConvertStrategy.java
new file mode 100644
index 000000000..6699bcbcb
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtConvertStrategy.java
@@ -0,0 +1,47 @@
+/*
+ * 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.jwt.strategy;
+
+import org.apache.shenyu.plugin.jwt.rule.JwtRuleHandle;
+import org.apache.shenyu.spi.SPI;
+import org.springframework.web.server.ServerWebExchange;
+
+import java.util.Map;
+
+@SPI
+public interface JwtConvertStrategy<T extends JwtRuleHandle> {
+
+    /**
+     * parse handleJson into jwtRuleHandle.
+     *
+     * @param handleJson handleJson from rule
+     * @return jwtRuleHandle
+     */
+    T parseHandleJson(String handleJson);
+
+    /**
+     * handle exchange by jwtRuleHandle and jwtBody.
+     *
+     * @param jwtRuleHandle jwtRuleHandle
+     * @param exchange      exchange
+     * @param jwtBody       jwtBody
+     * @return serverWebExchange
+     */
+    ServerWebExchange convert(T jwtRuleHandle, ServerWebExchange exchange, 
Map<String, Object> jwtBody);
+
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtConvertStrategyFactory.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtConvertStrategyFactory.java
new file mode 100644
index 000000000..ecc33ae99
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtConvertStrategyFactory.java
@@ -0,0 +1,41 @@
+/*
+ * 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.jwt.strategy;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.spi.ExtensionLoader;
+
+public class JwtConvertStrategyFactory {
+
+    private static final String DEFAULT_JWT_CONVERTER = "default";
+
+    /**
+     * new instance jwtConvertStrategy.
+     *
+     * @param handleType handleType
+     * @return jwtConvertStrategy
+     */
+    @SuppressWarnings("rawtypes")
+    public static JwtConvertStrategy newInstance(final String handleType) {
+        String type = handleType;
+        if (StringUtils.isBlank(type)) {
+            type = DEFAULT_JWT_CONVERTER;
+        }
+        return 
ExtensionLoader.getExtensionLoader(JwtConvertStrategy.class).getJoin(type);
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategy
 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategy
new file mode 100644
index 000000000..abc5c282b
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategy
@@ -0,0 +1,17 @@
+# 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.
+
+default=org.apache.shenyu.plugin.jwt.strategy.DefaultJwtConvertStrategy
\ No newline at end of file
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/JwtPluginTest.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/JwtPluginTest.java
index 415c514e1..3bcdb76a3 100644
--- 
a/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/JwtPluginTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/JwtPluginTest.java
@@ -17,15 +17,14 @@
 
 package org.apache.shenyu.plugin.jwt;
 
+import com.google.common.collect.ImmutableMap;
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.SignatureAlgorithm;
 import io.jsonwebtoken.security.Keys;
 import org.apache.shenyu.common.dto.PluginData;
 import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
-import org.apache.shenyu.common.dto.convert.rule.impl.JwtRuleHandle;
 import org.apache.shenyu.common.enums.PluginEnum;
-import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.plugin.api.ShenyuPluginChain;
 import org.apache.shenyu.plugin.api.result.DefaultShenyuResult;
 import org.apache.shenyu.plugin.api.result.ShenyuResult;
@@ -42,14 +41,13 @@ import reactor.core.publisher.Mono;
 import reactor.test.StepVerifier;
 
 import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.Map;
-import java.util.List;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 /**
@@ -67,93 +65,63 @@ public final class JwtPluginTest {
 
     private RuleData ruleData;
 
-    private JwtRuleHandle jwtRuleHandle;
+    private JwtPluginDataHandler jwtPluginDataHandlerUnderTest;
 
     @BeforeEach
     public void setUp() {
-        ConfigurableApplicationContext context = 
mock(ConfigurableApplicationContext.class);
-        when(context.getBean(ShenyuResult.class)).thenReturn(new 
DefaultShenyuResult());
-        SpringBeanUtils springBeanUtils = SpringBeanUtils.getInstance();
-        springBeanUtils.setApplicationContext(context);
-        PluginData pluginData = new PluginData("pluginId", "pluginName", 
"{\"secretKey\":\"shenyu-test-shenyu-test-shenyu-test\"}", "0", false);
-        JwtPluginDataHandler jwtPluginDataHandler = new JwtPluginDataHandler();
-        jwtPluginDataHandler.handlerPlugin(pluginData);
+        initContext();
         selectorData = mock(SelectorData.class);
         ruleData = new RuleData();
         jwtPluginUnderTest = new JwtPlugin();
-        // HMAC-SHA algorithms MUST have a size >= 256 bits
-        final String secreteKey = "shenyu-test-shenyu-test-shenyu-test";
-        Map<String, Object> map = new HashMap<>();
-        map.put("userId", 1);
-        Map<String, Object> multi = new HashMap<>();
-        multi.put("shenyu", "1.2.3");
-        map.put("web", multi);
-        Date date = new Date();
-        date.setTime(1636371125000L);
-        String token = Jwts.builder()
-                .setIssuedAt(date)
-                .setExpiration(new Date())
-                .setClaims(map)
-                
.signWith(Keys.hmacShaKeyFor(secreteKey.getBytes(StandardCharsets.UTF_8)), 
SignatureAlgorithm.HS256)
-                .compact();
-        jwtRuleHandle = new JwtRuleHandle();
-
-        exchange = MockServerWebExchange.from(MockServerHttpRequest
-                .get("localhost")
-                .header("token", token)
-                .build());
+        exchange = createServerWebExchange();
         chain = mock(ShenyuPluginChain.class);
+        jwtPluginDataHandlerUnderTest = new JwtPluginDataHandler();
     }
 
     @Test
-    public void testSecreteKey() {
-        PluginData pluginData = new PluginData("pluginId", "pluginName", 
"{\"secretKey\":\"\"}", "0", false);
-        JwtPluginDataHandler jwtPluginDataHandler = new JwtPluginDataHandler();
-        jwtPluginDataHandler.handlerPlugin(pluginData);
-        Mono<Void> mono = jwtPluginUnderTest.doExecute(exchange, chain, 
selectorData, ruleData);
-        StepVerifier.create(mono).expectSubscription().verifyComplete();
-    }
+    public void testDoExecute() {
 
-    @Test
-    public void testConverter() {
-        List<JwtRuleHandle.Convert> converts = new ArrayList<>();
-        JwtRuleHandle.Convert convert = new JwtRuleHandle.Convert();
-        convert.setJwtVal("userId");
-        convert.setHeaderVal("userId");
-        converts.add(convert);
-        jwtRuleHandle.setConverter(converts);
-        ruleData.setHandle(GsonUtils.getGson().toJson(jwtRuleHandle));
+        
ruleData.setHandle("{\"converter\":[{\"jwtVal\":\"userId\",\"headerVal\":\"id\"}]}");
+        jwtPluginDataHandlerUnderTest.handlerRule(ruleData);
         when(this.chain.execute(any())).thenReturn(Mono.empty());
+
         Mono<Void> mono = jwtPluginUnderTest.doExecute(exchange, chain, 
selectorData, ruleData);
+
         StepVerifier.create(mono).expectSubscription().verifyComplete();
+        verify(chain)
+                .execute(argThat(exchange -> hasHeader(exchange, "id", "1")));
+
     }
 
     @Test
-    public void testNullConverter() {
-        ruleData.setHandle(GsonUtils.getGson().toJson(jwtRuleHandle));
+    public void testDoExecuteWithCustomHandleType() {
+
+        
ruleData.setHandle("{\"handleType\":\"custom\",\"customConvert\":\"customConvert\"}");
+        jwtPluginDataHandlerUnderTest.handlerRule(ruleData);
         when(this.chain.execute(any())).thenReturn(Mono.empty());
+
         Mono<Void> mono = jwtPluginUnderTest.doExecute(exchange, chain, 
selectorData, ruleData);
+
         StepVerifier.create(mono).expectSubscription().verifyComplete();
+
+        verify(chain)
+                .execute(argThat(exchange -> hasHeader(exchange, "custom", 
"customConvert")));
     }
 
     @Test
-    public void testMulti() {
-        final List<JwtRuleHandle.Convert> converts = new ArrayList<>();
-        JwtRuleHandle.Convert webConvert = new JwtRuleHandle.Convert();
-        webConvert.setJwtVal("web.shenyu");
-        webConvert.setHeaderVal("shenyu");
-        JwtRuleHandle.Convert userConvert = new JwtRuleHandle.Convert();
-        userConvert.setJwtVal("userId");
-        userConvert.setHeaderVal("userId");
-        converts.add(userConvert);
-        converts.add(webConvert);
-        jwtRuleHandle.setConverter(converts);
-        ruleData.setHandle(GsonUtils.getGson().toJson(jwtRuleHandle));
+    public void testDoExecuteWithoutHandle() {
+
         when(this.chain.execute(any())).thenReturn(Mono.empty());
+
         Mono<Void> mono = jwtPluginUnderTest.doExecute(exchange, chain, 
selectorData, ruleData);
+
         StepVerifier.create(mono).expectSubscription().verifyComplete();
     }
 
+    private static boolean hasHeader(final ServerWebExchange exchange, final 
String name, final String val) {
+        return exchange.getRequest().getHeaders().get(name).contains(val);
+    }
+
     @Test
     public void testNamed() {
         final String result = jwtPluginUnderTest.named();
@@ -166,4 +134,33 @@ public final class JwtPluginTest {
         Assertions.assertEquals(PluginEnum.JWT.getCode(), result);
     }
 
+    private void initContext() {
+        ConfigurableApplicationContext context = 
mock(ConfigurableApplicationContext.class);
+        when(context.getBean(ShenyuResult.class)).thenReturn(new 
DefaultShenyuResult());
+        SpringBeanUtils springBeanUtils = SpringBeanUtils.getInstance();
+        springBeanUtils.setApplicationContext(context);
+        PluginData pluginData = new PluginData("pluginId", "pluginName", 
"{\"secretKey\":\"shenyu-test-shenyu-test-shenyu-test\"}", "0", false);
+        JwtPluginDataHandler jwtPluginDataHandler = new JwtPluginDataHandler();
+        jwtPluginDataHandler.handlerPlugin(pluginData);
+    }
+
+    private ServerWebExchange createServerWebExchange() {
+
+        // HMAC-SHA algorithms MUST have a size >= 256 bits
+        final String secreteKey = "shenyu-test-shenyu-test-shenyu-test";
+
+        Map<String, Object> map = ImmutableMap.<String, 
Object>builder().put("userId", 1).build();
+
+        String token = Jwts.builder()
+                .setIssuedAt(new Date(1636371125000L))
+                .setExpiration(new Date())
+                .setClaims(map)
+                
.signWith(Keys.hmacShaKeyFor(secreteKey.getBytes(StandardCharsets.UTF_8)), 
SignatureAlgorithm.HS256)
+                .compact();
+
+        return MockServerWebExchange.from(MockServerHttpRequest
+                .get("localhost")
+                .header("token", token)
+                .build());
+    }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandlerTest.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandlerTest.java
index cbc3af427..8c761bf07 100644
--- 
a/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandlerTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandlerTest.java
@@ -19,7 +19,6 @@ package org.apache.shenyu.plugin.jwt.handle;
 
 import org.apache.shenyu.common.dto.PluginData;
 import org.apache.shenyu.common.dto.RuleData;
-import org.apache.shenyu.common.dto.convert.rule.impl.JwtRuleHandle;
 import org.apache.shenyu.common.enums.PluginEnum;
 import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.common.utils.Singleton;
@@ -28,8 +27,6 @@ import org.apache.shenyu.plugin.jwt.config.JwtConfig;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -41,18 +38,9 @@ public final class JwtPluginDataHandlerTest {
 
     private JwtPluginDataHandler jwtPluginDataHandlerUnderTest;
 
-    private List<JwtRuleHandle.Convert> converts;
-
-    private JwtRuleHandle.Convert convert;
-
-    private JwtRuleHandle jwtRuleHandle;
-
     @BeforeEach
     public void setUp() {
         jwtPluginDataHandlerUnderTest = new JwtPluginDataHandler();
-        converts = new ArrayList<>();
-        convert = new JwtRuleHandle.Convert();
-        jwtRuleHandle = new JwtRuleHandle();
     }
 
     @Test
@@ -69,14 +57,10 @@ public final class JwtPluginDataHandlerTest {
         RuleData ruleData = new RuleData();
         ruleData.setId("jwtRule");
         ruleData.setSelectorId("jwt");
-        convert.setJwtVal("userId");
-        convert.setHeaderVal("userId");
-        converts.add(convert);
-        jwtRuleHandle.setConverter(converts);
-
-        ruleData.setHandle(GsonUtils.getGson().toJson(jwtRuleHandle));
+        String handleJson = 
"{\"converter\":[{\"jwtVal\":\"sub\",\"headerVal\":\"id\"}]}";
+        ruleData.setHandle(handleJson);
         jwtPluginDataHandlerUnderTest.handlerRule(ruleData);
-        assertEquals(jwtRuleHandle.getConverter().toString(), 
JwtPluginDataHandler.CACHED_HANDLE.get().obtainHandle(CacheKeyUtils.INST.getKey(ruleData)).getConverter().toString());
+        assertEquals(handleJson, 
JwtPluginDataHandler.CACHED_HANDLE.get().obtainHandle(CacheKeyUtils.INST.getKey(ruleData)).toJson());
     }
 
     @Test
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/rule/CustomJwtRuleHandle.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/rule/CustomJwtRuleHandle.java
new file mode 100644
index 000000000..2e76f91b8
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/rule/CustomJwtRuleHandle.java
@@ -0,0 +1,42 @@
+/*
+ * 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.jwt.rule;
+
+public class CustomJwtRuleHandle extends JwtRuleHandle {
+
+    private String customConvert;
+
+    /**
+     * get customConvert.
+     *
+     * @return customConvert
+     */
+    public String getCustomConvert() {
+        return customConvert;
+    }
+
+    /**
+     * set customConvert.
+     *
+     * @param customConvert customConvert
+     */
+    public void setCustomConvert(final String customConvert) {
+        this.customConvert = customConvert;
+    }
+
+}
diff --git 
a/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/rule/impl/JwtRuleHandleTest.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/rule/JwtRuleHandleTest.java
similarity index 54%
rename from 
shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/rule/impl/JwtRuleHandleTest.java
rename to 
shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/rule/JwtRuleHandleTest.java
index f53560386..70c9ff2bb 100644
--- 
a/shenyu-common/src/test/java/org/apache/shenyu/common/dto/convert/rule/impl/JwtRuleHandleTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/rule/JwtRuleHandleTest.java
@@ -15,39 +15,29 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.common.dto.convert.rule.impl;
+package org.apache.shenyu.plugin.jwt.rule;
 
 import org.junit.jupiter.api.Test;
 
-import java.util.Arrays;
-
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.core.Is.is;
+import static org.hamcrest.Matchers.isA;
+import static org.hamcrest.Matchers.nullValue;
 
 /**
- * Test case for JwtRuleHandle.
+ * Test case for {@link JwtRuleHandle}.
  */
 public class JwtRuleHandleTest {
-    
-    @Test
-    public void testGetterSetter() {
-        JwtRuleHandle handle = new JwtRuleHandle();
-        
-        handle.setConverter(Arrays.asList(new JwtRuleHandle.Convert()));
-        
-        assertThat(handle.getConverter(), hasSize(1));
-    }
-    
+
     @Test
-    public void testGetterSetterOfConvert() {
-        JwtRuleHandle.Convert convert = new JwtRuleHandle.Convert();
-        
-        convert.setHeaderVal("headerVal");
-        convert.setJwtVal("jwtVal");
-        
-        assertThat(convert.getHeaderVal(), is("headerVal"));
-        assertThat(convert.getJwtVal(), is("jwtVal"));
+    public void testGetInstance() {
+
+        assertThat(JwtRuleHandle.newInstance(null), nullValue());
+
+        assertThat(JwtRuleHandle.newInstance("{\"handleType\":\"custom\"}"),
+                isA(CustomJwtRuleHandle.class));
+
+        
assertThat(JwtRuleHandle.newInstance("{\"converter\":[{\"jwtVal\":\"sub\",\"headerVal\":\"id\"}]}"),
+                isA(DefaultJwtRuleHandle.class));
     }
-    
+
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/strategy/CustomJwtConvertStrategy.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/strategy/CustomJwtConvertStrategy.java
new file mode 100644
index 000000000..2f542319e
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/strategy/CustomJwtConvertStrategy.java
@@ -0,0 +1,46 @@
+/*
+ * 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.jwt.strategy;
+
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.plugin.jwt.rule.CustomJwtRuleHandle;
+import org.apache.shenyu.spi.Join;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.web.server.ServerWebExchange;
+
+import java.util.Map;
+
+@Join
+public class CustomJwtConvertStrategy implements 
JwtConvertStrategy<CustomJwtRuleHandle> {
+
+    @Override
+    public CustomJwtRuleHandle parseHandleJson(final String handleJson) {
+
+        return GsonUtils.getInstance().fromJson(handleJson, 
CustomJwtRuleHandle.class);
+    }
+
+    @Override
+    public ServerWebExchange convert(final CustomJwtRuleHandle jwtRuleHandle, 
final ServerWebExchange exchange, final Map<String, Object> jwtBody) {
+
+        String customConvert = jwtRuleHandle.getCustomConvert();
+        ServerHttpRequest modifiedRequest =
+                exchange.getRequest().mutate().header("custom", 
customConvert).build();
+
+        return exchange.mutate().request(modifiedRequest).build();
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtConvertStrategyTest.java
 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtConvertStrategyTest.java
new file mode 100644
index 000000000..4a317d2bf
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtConvertStrategyTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.jwt.strategy;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.shenyu.plugin.jwt.rule.DefaultJwtRuleHandle;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
+import org.springframework.mock.web.server.MockServerWebExchange;
+import org.springframework.web.server.ServerWebExchange;
+
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public class DefaultJwtConvertStrategyTest {
+
+    private DefaultJwtConvertStrategy defaultJwtConvertStrategy;
+
+    private ServerWebExchange exchange;
+
+    private Map<String, Object> jwtBody;
+
+    @BeforeEach
+    public void setUp() {
+        defaultJwtConvertStrategy = new DefaultJwtConvertStrategy();
+
+        exchange = MockServerWebExchange.from(MockServerHttpRequest
+                .get("localhost")
+                .build());
+
+        jwtBody = ImmutableMap.of("sub", "12345",
+                "multi", ImmutableMap.of("web", "shenyu"));
+
+    }
+
+    @Test
+    public void testParseHandleJson() {
+        String handleJson = 
"{\"converter\":[{\"jwtVal\":\"sub\",\"headerVal\":\"id\"}]}";
+        assertThat(defaultJwtConvertStrategy.parseHandleJson(handleJson), 
notNullValue(DefaultJwtRuleHandle.class));
+        assertThat(defaultJwtConvertStrategy.parseHandleJson(null), 
nullValue());
+    }
+
+    @Test
+    public void testConvert() {
+        String handleJson = 
"{\"converter\":[{\"jwtVal\":\"sub\",\"headerVal\":\"id\"}]}";
+        DefaultJwtRuleHandle defaultJwtRuleHandle = 
defaultJwtConvertStrategy.parseHandleJson(handleJson);
+        ServerWebExchange newExchange = defaultJwtConvertStrategy
+                .convert(defaultJwtRuleHandle, exchange, jwtBody);
+
+        
assertTrue(newExchange.getRequest().getHeaders().get("id").contains(jwtBody.get("sub")));
+
+    }
+
+    @Test
+    public void testExecuteWithWrongHandleJson() {
+
+        String wrongHandleJson = 
"{\"wrongConverter\":[{\"jwtVal\":\"sub\",\"headerVal\":\"id\"}]}";
+        DefaultJwtRuleHandle defaultJwtRuleHandle = 
defaultJwtConvertStrategy.parseHandleJson(wrongHandleJson);
+
+        ServerWebExchange newExchange = defaultJwtConvertStrategy
+                .convert(defaultJwtRuleHandle, exchange, jwtBody);
+
+        assertEquals(newExchange, exchange);
+
+    }
+
+    @Test
+    public void testExecuteWithWrongConverter() {
+
+        String wrongHandleJson = "{\"converter\":[{\"jwtVal 
\":\"sub\",\"headerVal \":\"id\"}]}";
+        DefaultJwtRuleHandle defaultJwtRuleHandle = 
defaultJwtConvertStrategy.parseHandleJson(wrongHandleJson);
+
+        ServerWebExchange newExchange = defaultJwtConvertStrategy
+                .convert(defaultJwtRuleHandle, exchange, jwtBody);
+
+        assertEquals(newExchange.getRequest().getHeaders(), 
exchange.getRequest().getHeaders());
+
+    }
+
+    @Test
+    public void testMulti() {
+        String handleJson = 
"{\"converter\":[{\"jwtVal\":\"multi.web\",\"headerVal\":\"web\"}]}";
+
+        DefaultJwtRuleHandle defaultJwtRuleHandle = defaultJwtConvertStrategy
+                .parseHandleJson(handleJson);
+
+        ServerWebExchange newExchange = defaultJwtConvertStrategy
+                .convert(defaultJwtRuleHandle, exchange, jwtBody);
+
+        
assertTrue(newExchange.getRequest().getHeaders().get("web").contains("shenyu"));
+    }
+
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-jwt/src/test/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategy
 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategy
new file mode 100644
index 000000000..0691af9f6
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-jwt/src/test/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtConvertStrategy
@@ -0,0 +1,17 @@
+# 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.
+
+custom=org.apache.shenyu.plugin.jwt.strategy.CustomJwtConvertStrategy
\ No newline at end of file

Reply via email to