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