This is an automated email from the ASF dual-hosted git repository.
xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new 0acf278 [ISSUE #2009] Enhance the ability of jwt plugin (#2319)
0acf278 is described below
commit 0acf2784fa18e723d1f3e2f9e1686938d6f33b07
Author: Sinsy <[email protected]>
AuthorDate: Thu Nov 11 14:35:49 2021 +0800
[ISSUE #2009] Enhance the ability of jwt plugin (#2319)
* Enhance the ability of jwt plugin
* fix JwtPluginTest
---
.../src/main/resources/sql-script/h2/schema.sql | 3 +-
.../src/main/resources/sql-script/mysql/schema.sql | 3 +-
.../src/main/resources/sql-script/pg/schema.sql | 2 +-
.../dto/convert/rule/impl/JwtRuleHandle.java | 109 +++++++++++++++++++++
.../test/http/combination/JwtPluginTest.java | 7 +-
.../org/apache/shenyu/plugin/jwt/JwtPlugin.java | 89 +++++++++++++----
.../apache/shenyu/plugin/jwt/config/JwtConfig.java | 23 -----
.../plugin/jwt/handle/JwtPluginDataHandler.java | 20 +++-
.../apache/shenyu/plugin/jwt/JwtPluginTest.java | 68 ++++++++++++-
.../jwt/handle/JwtPluginDataHandlerTest.java | 33 ++++++-
.../plugin/waf/handler/WafPluginDataHandler.java | 2 +-
11 files changed, 293 insertions(+), 66 deletions(-)
diff --git a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
index 44c64bb..dc09f37 100644
--- a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
@@ -337,7 +337,7 @@ INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`,
`config`, `enabled`,
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `enabled`,
`date_created`, `date_updated`) VALUES ('16', 'redirect', 'HttpProcess',
110,'0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`,
`enabled`, `date_created`, `date_updated`) VALUES ('17', 'motan', 'Proxy',
310,'{"register":"127.0.0.1:2181"}','0', '2020-11-09 01:19:10', '2020-11-09
01:19:10');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `enabled`,
`date_created`, `date_updated`) VALUES ('18', 'logging', 'Logging', 160, '0',
'2021-04-29 13:37:35', '2021-04-29 13:37:35');
-INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`,
`enabled`, `date_created`, `date_updated`) VALUES ('19', 'jwt',
'Authentication', 30, '{"secretKey":"key","filterPath":""}', '0', '2021-05-24
17:58:37', '2021-05-25 15:38:04');
+INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`,
`enabled`, `date_created`, `date_updated`) VALUES ('19', 'jwt',
'Authentication', 30, '{"secretKey":"key"}', '0', '2021-05-24 17:58:37',
'2021-05-25 15:38:04');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `enabled`,
`date_created`, `date_updated`) VALUES ('20', 'request', 'HttpProcess', 120,
'0', '2021-05-26 21:38:48', '2021-05-30 19:55:22');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `enabled`,
`date_created`, `date_updated`) VALUES ('21', 'oauth2', 'Authentication', 40,
'0', '2021-06-18 10:53:42', '2021-06-18 10:53:42');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`,
`enabled`, `date_created`, `date_updated`) VALUES ('22',
'paramMapping','HttpProcess', 70,'{"ruleHandlePageType":"custom"}', '0',
'2021-06-17 22:34:44', '2021-06-17 22:36:00');
@@ -459,7 +459,6 @@ INSERT IGNORE INTO plugin_handle
(`id`,`plugin_id`,`field`,`label`,`data_type`,`
/*insert plugin_handle data for plugin jwt*/
INSERT IGNORE INTO plugin_handle
(`id`,`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`,`date_created`,`date_updated`)
VALUES ('89','19' ,'secretKey','secretKey',2, 3, 0, null, '2020-11-09
01:19:10', '2020-11-09 01:19:10');
-INSERT IGNORE INTO plugin_handle
(`id`,`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`,`date_created`,`date_updated`)
VALUES ('90','19' ,'filterPath','filterPath',2, 3, 1, null, '2021-06-12
19:17:10', '2021-06-12 19:17:10');
/*insert plugin_handle data for plugin Cryptor*/
INSERT IGNORE INTO plugin_handle
(`id`,`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`,`date_created`,`date_updated`)
VALUES ('101', '24', 'strategyName', 'strategyName', 3, 2, 1, NULL,
'2021-08-06 14:35:50', '2021-08-06 14:35:50');
diff --git a/shenyu-admin/src/main/resources/sql-script/mysql/schema.sql
b/shenyu-admin/src/main/resources/sql-script/mysql/schema.sql
index 953013b..eb25de7 100644
--- a/shenyu-admin/src/main/resources/sql-script/mysql/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/mysql/schema.sql
@@ -339,7 +339,7 @@ INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`,
`config`, `enabled`,
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `enabled`,
`date_created`, `date_updated`) VALUES ('16', 'redirect', 'HttpProcess',
110,'0', '2020-11-09 01:19:10', '2020-11-09 01:19:10');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`,
`enabled`, `date_created`, `date_updated`) VALUES ('17', 'motan', 'Proxy',
310,'{"register":"127.0.0.1:2181"}','0', '2020-11-09 01:19:10', '2020-11-09
01:19:10');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `enabled`,
`date_created`, `date_updated`) VALUES ('18', 'logging', 'Logging', 160, '0',
'2021-04-29 13:37:35', '2021-04-29 13:37:35');
-INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`,
`enabled`, `date_created`, `date_updated`) VALUES ('19', 'jwt',
'Authentication', 30, '{"secretKey":"key","filterPath":""}', '0', '2021-05-24
17:58:37', '2021-05-25 15:38:04');
+INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`,
`enabled`, `date_created`, `date_updated`) VALUES ('19', 'jwt',
'Authentication', 30, '{"secretKey":"key"}', '0', '2021-05-24 17:58:37',
'2021-05-25 15:38:04');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `enabled`,
`date_created`, `date_updated`) VALUES ('20', 'request', 'HttpProcess', 120,
'0', '2021-05-26 21:38:48', '2021-05-30 19:55:22');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `enabled`,
`date_created`, `date_updated`) VALUES ('21', 'oauth2', 'Authentication', 40,
'0', '2021-06-18 10:53:42', '2021-06-18 10:53:42');
INSERT IGNORE INTO `plugin` (`id`, `name`, `role`, `sort`, `config`,
`enabled`, `date_created`, `date_updated`) VALUES ('22',
'paramMapping','HttpProcess', 70,'{"ruleHandlePageType":"custom"}', '0',
'2021-06-17 22:34:44', '2021-06-17 22:36:00');
@@ -461,7 +461,6 @@ INSERT IGNORE INTO plugin_handle
(`id`,`plugin_id`,`field`,`label`,`data_type`,`
/*insert plugin_handle data for plugin jwt*/
INSERT IGNORE INTO plugin_handle
(`id`,`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`,`date_created`,`date_updated`)
VALUES ('89','19' ,'secretKey','secretKey',2, 3, 0, null, '2020-11-09
01:19:10', '2020-11-09 01:19:10');
-INSERT IGNORE INTO plugin_handle
(`id`,`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`,`date_created`,`date_updated`)
VALUES ('90','19' ,'filterPath','filterPath',2, 3, 1, null, '2021-06-12
19:17:10', '2021-06-12 19:17:10');
/*insert plugin_handle data for plugin Cryptor*/
INSERT IGNORE INTO plugin_handle
(`id`,`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`,`date_created`,`date_updated`)
VALUES ('101', '24', 'strategyName', 'strategyName', 3, 2, 1, NULL,
'2021-08-06 14:35:50', '2021-08-06 14:35:50');
diff --git a/shenyu-admin/src/main/resources/sql-script/pg/schema.sql
b/shenyu-admin/src/main/resources/sql-script/pg/schema.sql
index 153bc5d..194336a 100644
--- a/shenyu-admin/src/main/resources/sql-script/pg/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/pg/schema.sql
@@ -662,7 +662,7 @@ ELSE
PERFORM public.dblink_exec('init_conn', 'INSERT INTO "plugin" VALUES
(''' || '16' || ''', ''' || 'redirect' || ''', NULL, ''' || 'HttpProcess' ||
''', 110, 0, ''' || '2020-11-09 01:19:10' || ''', ''' || '2020-11-09 01:19:10'
|| ''');');
PERFORM public.dblink_exec('init_conn', 'INSERT INTO "plugin" VALUES
(''' || '17' || ''', ''' || 'motan' || ''', ''' ||
'{"register":"127.0.0.1:2181"}' || ''', ''' || 'Proxy' || ''', 310, 0, ''' ||
'2020-11-09 01:19:10' || ''', ''' || '2020-11-09 01:19:10' || ''');');
PERFORM public.dblink_exec('init_conn', 'INSERT INTO "plugin" VALUES
(''' || '18' || ''', ''' || 'logging' || ''', NULL, ''' || 'Logging' || ''',
160, 0, ''' || '2021-04-29 13:37:35' || ''', ''' || '2021-04-29 13:37:35' ||
''');');
- PERFORM public.dblink_exec('init_conn', 'INSERT INTO "plugin" VALUES
(''' || '19' || ''', ''' || 'jwt' || ''', ''' ||
'{"secretKey":"key","filterPath":""}' || ''', ''' || 'Authentication' || ''',
30, 0, ''' || '2021-05-24 17:58:37' || ''', ''' || '2021-05-25 15:38:04' ||
''');');
+ PERFORM public.dblink_exec('init_conn', 'INSERT INTO "plugin" VALUES
(''' || '19' || ''', ''' || 'jwt' || ''', ''' || '{"secretKey":"key"}' || ''',
''' || 'Authentication' || ''', 30, 0, ''' || '2021-05-24 17:58:37' || ''', '''
|| '2021-05-25 15:38:04' || ''');');
PERFORM public.dblink_exec('init_conn', 'INSERT INTO "plugin" VALUES
(''' || '2' || ''', ''' || 'waf' || ''', ''' || '{"model":"black"}' || ''', '''
|| 'Authentication' || ''', 50, 0, ''' || '2018-06-23 10:26:30' || ''', ''' ||
'2018-06-13 15:43:10' || ''');');
PERFORM public.dblink_exec('init_conn', 'INSERT INTO "plugin" VALUES
(''' || '20' || ''', ''' || 'request' || ''', NULL, ''' || 'HttpProcess' ||
''', 120, 0, ''' || '2021-05-26 21:38:48' || ''', ''' || '2021-05-30 19:55:22'
|| ''');');
PERFORM public.dblink_exec('init_conn', 'INSERT INTO "plugin" VALUES
(''' || '21' || ''', ''' || 'oauth2' || ''', NULL, ''' || 'Authentication' ||
''', 40, 0, ''' || '2021-06-18 10:53:42' || ''', ''' || '2021-06-18 10:53:42'
|| ''');');
diff --git
a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/JwtRuleHandle.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/JwtRuleHandle.java
new file mode 100644
index 0000000..442edf3
--- /dev/null
+++
b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/JwtRuleHandle.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.common.dto.convert.rule.impl;
+
+import org.apache.shenyu.common.dto.convert.rule.RuleHandle;
+
+import java.util.List;
+
+/**
+ * Jwt rule handle.
+ */
+public class JwtRuleHandle implements RuleHandle {
+
+ /**
+ * converter, Jwt's body content is assigned to the header.
+ */
+ private List<Convert> converter;
+
+ /**
+ * get converter.
+ * @return List
+ */
+ 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) {
+ this.converter = converter;
+ }
+
+ public static class Convert {
+
+ /**
+ * jwt of body name.
+ */
+ private String jwtVal;
+
+ /**
+ * header name.
+ */
+ private String headerVal;
+
+ /**
+ * get jwtVal.
+ * @return jwtVal
+ */
+ public String getJwtVal() {
+ return jwtVal;
+ }
+
+ /**
+ * set jwtVal.
+ * @param jwtVal jwtVal
+ */
+ public void setJwtVal(final String jwtVal) {
+ this.jwtVal = jwtVal;
+ }
+
+ /**
+ * get headerVal.
+ * @return headerVal
+ */
+ public String getHeaderVal() {
+ return headerVal;
+ }
+
+ /**
+ * set headerVal.
+ * @param headerVal headerVal
+ */
+ public void setHeaderVal(final String headerVal) {
+ this.headerVal = headerVal;
+ }
+
+ @Override
+ public String toString() {
+ return "Convert{"
+ + "jwtVal='" + jwtVal + '\''
+ + ", headerVal='" + headerVal + '\''
+ + '}';
+ }
+ }
+}
diff --git
a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/JwtPluginTest.java
b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/JwtPluginTest.java
index 946647e..e5038ed 100644
---
a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/JwtPluginTest.java
+++
b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/JwtPluginTest.java
@@ -45,7 +45,7 @@ public final class JwtPluginTest extends
AbstractPluginDataInit {
@BeforeClass
public static void setup() throws IOException {
- String pluginResult = initPlugin(PluginEnum.JWT.getName(),
"{\"secretKey\":\"key00000\",\"filterPath\":\"/http/test/path/1111/name\"}");
+ String pluginResult = initPlugin(PluginEnum.JWT.getName(),
"{\"secretKey\":\"key00000\"}");
assertThat(pluginResult, is("success"));
String selectorAndRulesResult =
initSelectorAndRules(PluginEnum.JWT.getName(), "",
buildSelectorConditionList(), buildRuleLocalDataList());
assertThat(selectorAndRulesResult, is("success"));
@@ -55,14 +55,9 @@ public final class JwtPluginTest extends
AbstractPluginDataInit {
public void testJwt() throws IOException {
final String key = "key00000";
final String testPath = "/http/test/findByUserId?userId=1001";
- final String filterPath = "/http/test/path/1111/name";
final String token =
Jwts.builder().setId("1001").signWith(SignatureAlgorithm.HS256,
key.getBytes(StandardCharsets.UTF_8)).compact();
Map<String, Object> headers = new HashMap<>();
- // send request to filterPath
- Map<String, Object> filterResponse =
HttpHelper.INSTANCE.getFromGateway(filterPath, Map.class);
- assertThat(filterResponse.get("userId"), is("1111"));
-
// send request with fake jwt
headers.put("token", "fake.token.me");
Map<String, Object> errorResponse =
HttpHelper.INSTANCE.getFromGateway(testPath, headers, Map.class);
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 779c7a7..d495d1f 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
@@ -17,13 +17,15 @@
package org.apache.shenyu.plugin.jwt;
+import io.jsonwebtoken.Jwt;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
-import org.apache.commons.collections4.CollectionUtils;
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.plugin.api.ShenyuPluginChain;
import org.apache.shenyu.plugin.api.result.ShenyuResultEnum;
import org.apache.shenyu.plugin.api.result.ShenyuResultWrap;
@@ -33,11 +35,13 @@ import org.apache.shenyu.plugin.jwt.config.JwtConfig;
import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
import org.apache.shenyu.plugin.jwt.exception.ThrowingFunction;
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;
/**
* Jwt Plugin.
@@ -53,22 +57,25 @@ public class JwtPlugin extends AbstractShenyuPlugin {
JwtConfig jwtConfig = Singleton.INST.get(JwtConfig.class);
String authorization =
exchange.getRequest().getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
String token = exchange.getRequest().getHeaders().getFirst(TOKEN);
- // filter path
- String path = exchange.getRequest().getURI().getPath();
- List<String> filterPath = jwtConfig.getFilterPath();
- if (CollectionUtils.isNotEmpty(filterPath)) {
- if (filterPath.contains(path)) {
- return chain.execute(exchange);
- }
- }
+
// check secreteKey
if (StringUtils.isEmpty(jwtConfig.getSecretKey())) {
Object error =
ShenyuResultWrap.error(ShenyuResultEnum.SECRET_KEY_MUST_BE_CONFIGURED.getCode(),
ShenyuResultEnum.SECRET_KEY_MUST_BE_CONFIGURED.getMsg(), null);
return WebFluxResultUtils.result(exchange, error);
}
+
// compatible processing
String finalAuthorization = compatible(token, authorization);
- return checkAuthorization(exchange, chain, finalAuthorization,
jwtConfig.getSecretKey());
+ Map<String, String> jwtBody = checkAuthorization(finalAuthorization,
jwtConfig.getSecretKey());
+ if (jwtBody != null) {
+ JwtRuleHandle ruleHandle =
GsonUtils.getInstance().fromJson(rule.getHandle(), JwtRuleHandle.class);
+ if (ruleHandle == null) {
+ return chain.execute(exchange);
+ }
+ return chain.execute(converter(exchange, jwtBody,
ruleHandle.getConverter()));
+ }
+ Object error =
ShenyuResultWrap.error(ShenyuResultEnum.ERROR_TOKEN.getCode(),
ShenyuResultEnum.ERROR_TOKEN.getMsg(), null);
+ return WebFluxResultUtils.result(exchange, error);
}
@Override
@@ -81,6 +88,12 @@ public class JwtPlugin extends AbstractShenyuPlugin {
return PluginEnum.JWT.getCode();
}
+ /**
+ * Both are compatible.
+ * @param token header of token
+ * @param authorization header of authorization
+ * @return the authorization after processing
+ */
private String compatible(final String token, final String authorization) {
String finalAuthorization;
if (StringUtils.isNotEmpty(token)) {
@@ -90,22 +103,60 @@ public class JwtPlugin extends AbstractShenyuPlugin {
} else {
return null;
}
- return finalAuthorization.contains(AUTH2_TOKEN) ?
finalAuthorization.split(" ")[1] : finalAuthorization;
+ return isAuth2(finalAuthorization) ? finalAuthorization.split(" ")[1]
: finalAuthorization;
}
- private Mono<Void> checkAuthorization(final ServerWebExchange exchange,
- final ShenyuPluginChain chain,
- final String authorization,
- final String secretKey) {
- Object error =
ShenyuResultWrap.error(ShenyuResultEnum.ERROR_TOKEN.getCode(),
ShenyuResultEnum.ERROR_TOKEN.getMsg(), null);
+ private boolean isAuth2(final String authorization) {
+ return authorization.contains(AUTH2_TOKEN);
+ }
+
+ /**
+ * check Authorization.
+ * @param authorization the authorization after processing
+ * @param secretKey secretKey of authorization
+ * @return Map
+ */
+ private Map<String, String> checkAuthorization(final String authorization,
+ final String secretKey) {
+
if (StringUtils.isEmpty(authorization)) {
- return WebFluxResultUtils.result(exchange, error);
+ return null;
}
JwtParser jwtParser = Jwts.parser();
if (jwtParser.isSigned(authorization)) {
jwtParser.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8));
- return ThrowingFunction.wrap(() -> jwtParser.parse(authorization))
== null ? WebFluxResultUtils.result(exchange, error) : chain.execute(exchange);
+ Jwt jwt = ThrowingFunction.wrap(() ->
jwtParser.parse(authorization));
+ return jwt == null ? null :
GsonUtils.getInstance().toObjectMap(String.valueOf(jwt.getBody()),
String.class);
+ }
+ 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, String> 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, String> body,
+ final List<JwtRuleHandle.Convert> converters) {
+ for (JwtRuleHandle.Convert converter : converters) {
+ headers.add(converter.getHeaderVal(),
body.get(converter.getJwtVal()));
}
- return WebFluxResultUtils.result(exchange, error);
}
}
diff --git
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/config/JwtConfig.java
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/config/JwtConfig.java
index dfd0958..d2bd2e3 100644
---
a/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/config/JwtConfig.java
+++
b/shenyu-plugin/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/config/JwtConfig.java
@@ -18,7 +18,6 @@
package org.apache.shenyu.plugin.jwt.config;
import java.io.Serializable;
-import java.util.List;
/**
* The type Jwt config.
@@ -31,11 +30,6 @@ public class JwtConfig implements Serializable {
private String secretKey;
/**
- * No need to carry the authorization.
- */
- private List<String> filterPath;
-
- /**
* Gets secret key.
*
* @return the secret key
@@ -53,21 +47,4 @@ public class JwtConfig implements Serializable {
this.secretKey = secretKey;
}
- /**
- * Gets filter path.
- *
- * @return the filter path
- */
- public List<String> getFilterPath() {
- return filterPath;
- }
-
- /**
- * Sets filter path.
- *
- * @param filterPath the filter path
- */
- public void setFilterPath(final List<String> filterPath) {
- this.filterPath = filterPath;
- }
}
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 225eda1..9c816e8 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
@@ -17,36 +17,48 @@
package org.apache.shenyu.plugin.jwt.handle;
-import org.apache.commons.lang3.StringUtils;
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.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 java.util.Arrays;
import java.util.Map;
import java.util.Optional;
+import java.util.function.Supplier;
/**
* Configuration data of the jwt plugin.
*/
public class JwtPluginDataHandler implements PluginDataHandler {
+ public static final Supplier<CommonHandleCache<String, JwtRuleHandle>>
CACHED_HANDLE = new BeanHolder<>(CommonHandleCache::new);
+
@Override
public void handlerPlugin(final PluginData pluginData) {
Map<String, String> configMap =
GsonUtils.getInstance().toObjectMap(pluginData.getConfig(), String.class);
String secretKey =
Optional.ofNullable(configMap.get(Constants.SECRET_KEY)).orElse("");
- String filterPath =
Optional.ofNullable(configMap.get(Constants.FILTER_PATH)).orElse("");
JwtConfig jwtConfig = new JwtConfig();
jwtConfig.setSecretKey(secretKey);
- jwtConfig.setFilterPath(Arrays.asList(StringUtils.split(filterPath,
",")));
Singleton.INST.single(JwtConfig.class, jwtConfig);
}
@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);
+ });
+ }
+
+ @Override
public String pluginNamed() {
return PluginEnum.JWT.getName();
}
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 594ab8e..8c537e4 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,10 +17,14 @@
package org.apache.shenyu.plugin.jwt;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
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;
@@ -29,12 +33,19 @@ import
org.apache.shenyu.plugin.jwt.handle.JwtPluginDataHandler;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.List;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -54,6 +65,14 @@ public final class JwtPluginTest {
private RuleData ruleData;
+ private String token;
+
+ private List<JwtRuleHandle.Convert> converts;
+
+ private JwtRuleHandle.Convert convert;
+
+ private JwtRuleHandle jwtRuleHandle;
+
@Before
public void setUp() {
ConfigurableApplicationContext context =
mock(ConfigurableApplicationContext.class);
@@ -61,7 +80,7 @@ public final class JwtPluginTest {
SpringBeanUtils springBeanUtils = SpringBeanUtils.getInstance();
springBeanUtils.setApplicationContext(context);
final PluginData pluginData =
- new PluginData("pluginId", "pluginName",
"{\"secretKey\":\"sinsy\",\"filterPath\":\"/cloud/ecg/common,/cloud/ecg/selectAll\"}",
"0", false);
+ new PluginData("pluginId", "pluginName",
"{\"secretKey\":\"shenyu\"}", "0", false);
JwtPluginDataHandler jwtPluginDataHandler = new JwtPluginDataHandler();
jwtPluginDataHandler.handlerPlugin(pluginData);
exchange =
MockServerWebExchange.from(MockServerHttpRequest.get("localhost").build());
@@ -70,23 +89,62 @@ public final class JwtPluginTest {
selectorData = mock(SelectorData.class);
ruleData = mock(RuleData.class);
jwtPluginUnderTest = new JwtPlugin();
+ converts = new ArrayList<>();
+ convert = mock(JwtRuleHandle.Convert.class);
+ String secreteKey = "shenyu";
+ Map<String, Object> map = new HashMap<>();
+ map.put("userId", 1);
+ Date date = new Date();
+ date.setTime(1636371125000L);
+ token = Jwts.builder()
+ .setIssuedAt(date)
+ .setExpiration(new Date())
+ .setClaims(map)
+ .signWith(SignatureAlgorithm.HS256, secreteKey)
+ .compact();
+ jwtRuleHandle = mock(JwtRuleHandle.class);
+
}
@Test
- public void doExecuteTest() {
- Mono<Void> mono = jwtPluginUnderTest.doExecute(exchange, chain,
selectorData, ruleData);
+ public void testSecreteKey() {
+ ServerHttpRequest newRequest =
exchange.getRequest().mutate().header("token", this.token).build();
+ ServerWebExchange webExchange =
exchange.mutate().request(newRequest).build();
+ Mono<Void> mono = jwtPluginUnderTest.doExecute(webExchange, chain,
selectorData, ruleData);
StepVerifier.create(mono).expectSubscription().verifyComplete();
}
@Test
- public void namedTest() {
+ public void testCompatible() {
+ ServerHttpRequest newRequest =
exchange.getRequest().mutate().header("token", this.token).build();
+ ServerWebExchange webExchange =
exchange.mutate().request(newRequest).build();
+ Mono<Void> mono = jwtPluginUnderTest.doExecute(webExchange, chain,
selectorData, ruleData);
+ StepVerifier.create(mono).expectSubscription().verifyComplete();
+ }
+
+ @Test
+ public void testConverter() {
+ final ServerHttpRequest newRequest =
exchange.getRequest().mutate().header("token", this.token).build();
+ convert.setJwtVal("userId");
+ convert.setHeaderVal("userId");
+ converts.add(convert);
+ jwtRuleHandle.setConverter(converts);
+ ruleData.setHandle(GsonUtils.getGson().toJson(jwtRuleHandle));
+ ServerWebExchange webExchange =
exchange.mutate().request(newRequest).build();
+ Mono<Void> mono = jwtPluginUnderTest.doExecute(webExchange, chain,
selectorData, ruleData);
+ StepVerifier.create(mono).expectSubscription().verifyComplete();
+ }
+
+ @Test
+ public void testNamed() {
final String result = jwtPluginUnderTest.named();
assertEquals(PluginEnum.JWT.getName(), result);
}
@Test
- public void getOrderTest() {
+ public void testGetOrder() {
final int result = jwtPluginUnderTest.getOrder();
assertEquals(PluginEnum.JWT.getCode(), result);
}
+
}
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 8b19dba..3491826 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
@@ -17,15 +17,19 @@
package org.apache.shenyu.plugin.jwt.handle;
-import org.apache.commons.lang3.StringUtils;
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.utils.CacheKeyUtils;
import org.apache.shenyu.plugin.jwt.config.JwtConfig;
import org.junit.Before;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
@@ -37,19 +41,42 @@ public final class JwtPluginDataHandlerTest {
private JwtPluginDataHandler jwtPluginDataHandlerUnderTest;
+ private List<JwtRuleHandle.Convert> converts;
+
+ private JwtRuleHandle.Convert convert;
+
+ private JwtRuleHandle jwtRuleHandle;
+
@Before
public void setUp() {
jwtPluginDataHandlerUnderTest = new JwtPluginDataHandler();
+ converts = new ArrayList<>();
+ convert = new JwtRuleHandle.Convert();
+ jwtRuleHandle = new JwtRuleHandle();
}
@Test
public void testHandlerPlugin() {
- final PluginData pluginData = new PluginData("pluginId", "pluginName",
"{\"secretKey\":\"sinsy\",\"filterPath\":\"/cloud/ecg/common,/cloud/ecg/selectAll\"}",
"0", false);
+ final PluginData pluginData = new PluginData("pluginId", "pluginName",
"{\"secretKey\":\"shenyu\"}", "0", false);
jwtPluginDataHandlerUnderTest.handlerPlugin(pluginData);
JwtConfig jwtConfig = Singleton.INST.get(JwtConfig.class);
Map<String, String> map =
GsonUtils.getInstance().toObjectMap(pluginData.getConfig(), String.class);
assertEquals(jwtConfig.getSecretKey(), map.get("secretKey"));
- assertEquals(StringUtils.join(jwtConfig.getFilterPath(), ","),
map.get("filterPath"));
+ }
+
+ @Test
+ public void testHandlerRule() {
+ 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));
+ jwtPluginDataHandlerUnderTest.handlerRule(ruleData);
+ assertEquals(jwtRuleHandle.getConverter().toString(),
JwtPluginDataHandler.CACHED_HANDLE.get().obtainHandle(CacheKeyUtils.INST.getKey(ruleData)).getConverter().toString());
}
@Test
diff --git
a/shenyu-plugin/shenyu-plugin-waf/src/main/java/org/apache/shenyu/plugin/waf/handler/WafPluginDataHandler.java
b/shenyu-plugin/shenyu-plugin-waf/src/main/java/org/apache/shenyu/plugin/waf/handler/WafPluginDataHandler.java
index 6f67a2d..657b83c 100644
---
a/shenyu-plugin/shenyu-plugin-waf/src/main/java/org/apache/shenyu/plugin/waf/handler/WafPluginDataHandler.java
+++
b/shenyu-plugin/shenyu-plugin-waf/src/main/java/org/apache/shenyu/plugin/waf/handler/WafPluginDataHandler.java
@@ -37,7 +37,7 @@ import java.util.function.Supplier;
*/
public class WafPluginDataHandler implements PluginDataHandler {
- public static final Supplier<CommonHandleCache<String, WafHandle>>
CACHED_HANDLE = new BeanHolder(CommonHandleCache::new);
+ public static final Supplier<CommonHandleCache<String, WafHandle>>
CACHED_HANDLE = new BeanHolder<>(CommonHandleCache::new);
@Override
public void handlerPlugin(final PluginData pluginData) {