From 8ca7f57b9cea25f3c326c6da2e767a38d68384de Mon Sep 17 00:00:00 2001 From: SKonst <346403746@qq.com> Date: Mon, 13 Jan 2025 09:59:49 +0800 Subject: [PATCH] [type:refactor] plugin-jwt SPI extension for parsing JWT payloads to ensure compatibility with older versions of JWT tools (#5882) * fix admin: The error occurs when testing the sandbox API, and the target method is not a POST request. * fix admin: Applied Checkstyle to HttpUtils file * refactor plugin-jwt: SPI extension for parsing JWT payloads to ensure compatibility with older versions of JWT tools * [type:upgrade] The field handleType extended by plugin-jwt needs to be added to the database table. Upgrade database initialization script and upgrade script --------- Co-authored-by: aias00 Co-authored-by: xiaoyu --- db/init/mysql/schema.sql | 2 + db/init/ob/schema.sql | 2 + db/init/og/create-table.sql | 2 + db/init/oracle/schema.sql | 2 + db/init/pg/create-table.sql | 2 + db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql | 18 ++++++ db/upgrade/2.7.0-upgrade-2.7.1-og.sql | 18 ++++++ db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql | 19 ++++++ db/upgrade/2.7.0-upgrade-2.7.1-pg.sql | 18 ++++++ db/upgrade/upgrade-guide.md | 62 +++++++------------ .../main/resources/sql-script/h2/schema.sql | 2 + .../apache/shenyu/plugin/jwt/JwtPlugin.java | 33 +++------- .../shenyu/plugin/jwt/config/JwtConfig.java | 22 +++++++ .../jwt/handle/JwtPluginDataHandler.java | 6 +- .../DefaultJwtPayloadParseStrategy.java | 44 +++++++++++++ .../jwt/strategy/JwtPayloadParseStrategy.java | 39 ++++++++++++ .../JwtPayloadParseStrategyFactory.java | 39 ++++++++++++ ...lugin.jwt.strategy.JwtPayloadParseStrategy | 17 +++++ 18 files changed, 283 insertions(+), 64 deletions(-) create mode 100755 db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql create mode 100644 db/upgrade/2.7.0-upgrade-2.7.1-og.sql create mode 100755 db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql create mode 100755 db/upgrade/2.7.0-upgrade-2.7.1-pg.sql create mode 100644 shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtPayloadParseStrategy.java create mode 100644 shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtPayloadParseStrategy.java create mode 100644 shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtPayloadParseStrategyFactory.java create mode 100644 shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtPayloadParseStrategy diff --git a/db/init/mysql/schema.sql b/db/init/mysql/schema.sql index 1d88800a6e64..d744628f1123 100644 --- a/db/init/mysql/schema.sql +++ b/db/init/mysql/schema.sql @@ -1299,6 +1299,8 @@ INSERT INTO `plugin_handle` VALUES ('1722804548510507029', '20', 'requestUniqueH INSERT INTO `plugin_handle` VALUES ('1722804548510507030', '20', 'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, '{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 22:37:48.239'); INSERT INTO `plugin_handle` VALUES ('1722804548510507031', '20', 'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, '{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 22:38:05.726'); +INSERT INTO `plugin_handle` VALUES ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}', '2025-01-02 17:20:50.233', '2025-01-02 17:20:50.233'); + -- ---------------------------- -- Table structure for resource -- ---------------------------- diff --git a/db/init/ob/schema.sql b/db/init/ob/schema.sql index cf0790759a7b..018749396f7f 100644 --- a/db/init/ob/schema.sql +++ b/db/init/ob/schema.sql @@ -1292,6 +1292,8 @@ INSERT INTO `plugin_handle` VALUES ('1722804548510507029', '20', 'requestUniqueH INSERT INTO `plugin_handle` VALUES ('1722804548510507030', '20', 'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, '{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 22:37:48.239'); INSERT INTO `plugin_handle` VALUES ('1722804548510507031', '20', 'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, '{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 22:38:05.726'); +INSERT INTO `plugin_handle` VALUES ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}', '2025-01-02 17:20:50.233', '2025-01-02 17:20:50.233'); + -- ---------------------------- -- Table structure for resource -- ---------------------------- diff --git a/db/init/og/create-table.sql b/db/init/og/create-table.sql index 4fed46732169..291b3ca0ac94 100644 --- a/db/init/og/create-table.sql +++ b/db/init/og/create-table.sql @@ -1376,6 +1376,8 @@ INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507029', '20', 'reque INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507030', '20', 'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, '{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 22:37:48.239'); INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507031', '20', 'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, '{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 22:38:05.726'); +INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}', '2025-01-02 17:20:50.233', '2025-01-02 17:20:50.233'); + -- ---------------------------- -- Table structure for resource -- ---------------------------- diff --git a/db/init/oracle/schema.sql b/db/init/oracle/schema.sql index 22463a224ee9..bdb79719b53d 100644 --- a/db/init/oracle/schema.sql +++ b/db/init/oracle/schema.sql @@ -2191,6 +2191,8 @@ values ('1722804548510507030', '20', 'respHeaderUniqueStrategy', 'respHeaderUniq insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) */ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, EXT_OBJ) values ('1722804548510507031', '20', 'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, '{"required":"0","rule":""}'); +insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) */ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, EXT_OBJ) +values ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}'); insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) */ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, ENABLED) diff --git a/db/init/pg/create-table.sql b/db/init/pg/create-table.sql index b49dc04cc513..9a5382574244 100644 --- a/db/init/pg/create-table.sql +++ b/db/init/pg/create-table.sql @@ -1436,6 +1436,8 @@ INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507029', '20', 'reque INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507030', '20', 'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, '{"required":"0","rule":""}', '2024-12-13 22:37:48.239', '2024-12-13 22:37:48.239'); INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507031', '20', 'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, '{"required":"0","rule":""}', '2024-12-13 22:38:05.726', '2024-12-13 22:38:05.726'); +INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}', '2025-01-02 17:20:50.233', '2025-01-02 17:20:50.233'); + -- ---------------------------- -- Table structure for resource -- ---------------------------- diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql b/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql new file mode 100755 index 000000000000..7e4a8d5c5389 --- /dev/null +++ b/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql @@ -0,0 +1,18 @@ +-- 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. + +-- this file works for MySQL. +INSERT INTO `plugin_handle` VALUES ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}', '2025-01-02 17:20:50.233', '2025-01-02 17:20:50.233'); \ No newline at end of file diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-og.sql b/db/upgrade/2.7.0-upgrade-2.7.1-og.sql new file mode 100644 index 000000000000..9df235bc6b1b --- /dev/null +++ b/db/upgrade/2.7.0-upgrade-2.7.1-og.sql @@ -0,0 +1,18 @@ +-- 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. + +-- this file works for og. +INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}', '2025-01-02 17:20:50.233', '2025-01-02 17:20:50.233'); \ No newline at end of file diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql b/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql new file mode 100755 index 000000000000..04d7c8189eac --- /dev/null +++ b/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql @@ -0,0 +1,19 @@ +-- 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. + +-- this file works for Oracle, can not use "`" syntax. +insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) */ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, EXT_OBJ) +values ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}'); diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql b/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql new file mode 100755 index 000000000000..3a2053effc68 --- /dev/null +++ b/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql @@ -0,0 +1,18 @@ +-- 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. + +-- this file works for PostgreSQL, can not use "`" syntax. +INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}', '2025-01-02 17:20:50.233', '2025-01-02 17:20:50.233'); diff --git a/db/upgrade/upgrade-guide.md b/db/upgrade/upgrade-guide.md index 04754be42301..1ac558b906ec 100644 --- a/db/upgrade/upgrade-guide.md +++ b/db/upgrade/upgrade-guide.md @@ -4,8 +4,30 @@ ## To Shenyu Users +- 2.7.0-upgrade-2.7.1-mysql.sql + +- 2.7.0-upgrade-2.7.1-og.sql + +- 2.7.0-upgrade-2.7.1-oracle.sql + +- 2.7.0-upgrade-2.7.1-pg.sql + + > this file is the Shenyu upgrade sql from v2.7.0 to v2.7.1 + +- 2.6.1-upgrade-2.7.0-mysql.sql + +- 2.6.1-upgrade-2.7.0-og.sql + +- 2.6.1-upgrade-2.7.0-oracle.sql + +- 2.6.1-upgrade-2.7.0-pg.sql + + > this file is the Shenyu upgrade sql from v2.6.1 to v2.7.0 + - 2.6.0-upgrade-2.6.1-mysql.sql +- 2.6.0-upgrade-2.6.1-og.sql + - 2.6.0-upgrade-2.6.1-oracle.sql - 2.6.0-upgrade-2.6.1-pg.sql @@ -14,6 +36,8 @@ - 2.5.1-upgrade-2.6.0-mysql.sql +- 2.5.1-upgrade-2.6.0-og.sql + - 2.5.1-upgrade-2.6.0-oracle.sql - 2.5.1-upgrade-2.6.0-pg.sql @@ -45,41 +69,3 @@ - 2.4.1-upgrade-2.4.2-pg.sql > this file is the Shenyu upgrade sql from v2.4.1 to v2.4.2 - -- 2.4.2-upgrade-2.4.3-mysql.sql - -- 2.4.2-upgrade-2.4.3-pg.sql - - > this file is the Shenyu upgrade sql from v2.4.2 to v2.4.3 - -- 2.4.3-upgrade-2.5.0-mysql.sql - -- 2.4.3-upgrade-2.5.0-pg.sql - - > this file is the Shenyu upgrade sql from v2.4.3 to v2.5.0 - -- 2.5.0-upgrade-2.5.1-mysql.sql - -- 2.5.0-upgrade-2.5.1-oracle.sql - -- 2.5.0-upgrade-2.5.1-pg.sql - - > this file is the Shenyu upgrade sql from v2.5.0 to v2.5.1 - -- 2.5.1-upgrade-2.6.0-mysql.sql - -- 2.5.1-upgrade-2.6.0-oracle.sql - -- 2.5.1-upgrade-2.6.0-pg.sql - - > this file is the Shenyu upgrade sql from v2.5.1 to v2.6.0 - -- 2.6.0-upgrade-2.6.1-mysql.sql - -- 2.6.0-upgrade-2.6.1-og.sql - -- 2.6.0-upgrade-2.6.1-oracle.sql - -- 2.6.0-upgrade-2.6.1-pg.sql - - > this file is the Shenyu upgrade sql from v2.6.0 to v2.6.1 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 b1dc97d5f4b4..4f7b671ae8ba 100755 --- a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql +++ b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql @@ -924,6 +924,8 @@ INSERT IGNORE INTO plugin_handle (`id`, `plugin_id`,`field`,`label`,`data_type`, INSERT IGNORE INTO plugin_handle (`id`, `plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES ('1722804548510507030', '20', 'respHeaderUniqueStrategy', 'respHeaderUniqueStrategy', 2, 2, 3, '{"required":"0","rule":""}'); INSERT IGNORE INTO plugin_handle (`id`, `plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES ('1722804548510507031', '20', 'respUniqueHeaders', 'respUniqueHeaders', 2, 2, 4, '{"required":"0","rule":""}'); +INSERT IGNORE INTO plugin_handle (`id`, `plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES ('1722804548510507032', '19', 'handleType', 'handleType', 2, 3, 1, '{"required":"0","rule":""}'); + /** insert resource for resource */ INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`, `component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`, `status`) VALUES('1346775491550474240','','SHENYU.MENU.PLUGIN.LIST','plug','/plug','PluginList','0','0','dashboard','0','0','','1'); diff --git a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java index 1977be828f60..66847f6d2dfb 100644 --- a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java +++ b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/JwtPlugin.java @@ -17,11 +17,6 @@ package org.apache.shenyu.plugin.jwt; -import io.jsonwebtoken.Jwt; -import io.jsonwebtoken.JwtParser; -import io.jsonwebtoken.JwtParserBuilder; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.security.Keys; import org.apache.commons.lang3.StringUtils; import org.apache.shenyu.common.dto.RuleData; import org.apache.shenyu.common.dto.SelectorData; @@ -34,11 +29,12 @@ 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.apache.shenyu.plugin.jwt.strategy.JwtPayloadParseStrategy; +import org.apache.shenyu.plugin.jwt.strategy.JwtPayloadParseStrategyFactory; import org.springframework.http.HttpHeaders; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @@ -67,7 +63,7 @@ protected Mono doExecute(final ServerWebExchange exchange, final ShenyuPlu } // compatible processing String finalAuthorization = compatible(token, authorization); - Map jwtBody = checkAuthorization(finalAuthorization, jwtConfig.getSecretKey()); + Map jwtBody = parseJwtPayload(finalAuthorization, jwtConfig); if (Objects.isNull(jwtBody)) { Object error = ShenyuResultWrap.error(exchange, ShenyuResultEnum.ERROR_TOKEN); return WebFluxResultUtils.result(exchange, error); @@ -118,29 +114,18 @@ private boolean isAuth2(final String authorization) { } /** - * check Authorization. + * parse jwt payload. * * @param authorization the authorization after processing - * @param secretKey secretKey of authorization + * @param jwtConfig the jwt config * @return Map */ - private Map checkAuthorization(final String authorization, - final String secretKey) { - + private Map parseJwtPayload(final String authorization, + final JwtConfig jwtConfig) { if (StringUtils.isEmpty(authorization)) { return null; } - JwtParserBuilder jwtParserBuilder = Jwts.parser(); - JwtParser jwtParser = jwtParserBuilder.build(); - if (jwtParser.isSigned(authorization)) { - jwtParserBuilder.verifyWith(Keys.hmacShaKeyFor(secretKey.getBytes())); - JwtParser jwtParserExec = jwtParserBuilder.build(); - Jwt jwt = ThrowingFunction.wrap(() -> jwtParserExec.parse(authorization)); - if (jwt == null) { - return null; - } - return (Map) jwt.getBody(); - } - return null; + JwtPayloadParseStrategy payloadParseStrategy = JwtPayloadParseStrategyFactory.newInstance(jwtConfig.getHandleType()); + return payloadParseStrategy.parse(jwtConfig.getSecretKey(), authorization); } } diff --git a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/config/JwtConfig.java b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/config/JwtConfig.java index d2bd2e30765f..9327dd2c309e 100644 --- a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/config/JwtConfig.java +++ b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/config/JwtConfig.java @@ -29,6 +29,11 @@ public class JwtConfig implements Serializable { */ private String secretKey; + /** + * private handleType. + */ + private String handleType; + /** * Gets secret key. * @@ -47,4 +52,21 @@ public void setSecretKey(final String secretKey) { this.secretKey = secretKey; } + /** + * Gets handleType. + * + * @return jwt payload handle type + */ + public String getHandleType() { + return handleType; + } + + /** + * Sets handleType. + * + * @param handleType jwt payload handle type + */ + public void setHandleType(final String handleType) { + this.handleType = handleType; + } } diff --git a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandler.java b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandler.java index 58044d22c255..b03d9be454cc 100644 --- a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandler.java +++ b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/handle/JwtPluginDataHandler.java @@ -45,16 +45,18 @@ public class JwtPluginDataHandler implements PluginDataHandler { public void handlerPlugin(final PluginData pluginData) { Map configMap = GsonUtils.getInstance().toObjectMap(pluginData.getConfig(), String.class); String secretKey = Optional.ofNullable(configMap.get(Constants.SECRET_KEY)).orElse(""); + String handleType = Optional.ofNullable(configMap.get("handleType")).orElse("default"); JwtConfig jwtConfig = new JwtConfig(); jwtConfig.setSecretKey(secretKey); + jwtConfig.setHandleType(handleType); Singleton.INST.single(JwtConfig.class, jwtConfig); } - + @Override public void removeRule(final RuleData ruleData) { CACHED_HANDLE.get().removeHandle(CacheKeyUtils.INST.getKey(ruleData)); } - + @Override public void handlerRule(final RuleData ruleData) { Optional.ofNullable(ruleData.getHandle()).ifPresent(ruleHandle -> { diff --git a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtPayloadParseStrategy.java b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtPayloadParseStrategy.java new file mode 100644 index 000000000000..0720695e0149 --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/DefaultJwtPayloadParseStrategy.java @@ -0,0 +1,44 @@ +/* + * 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 io.jsonwebtoken.Jwt; +import io.jsonwebtoken.JwtParser; +import io.jsonwebtoken.JwtParserBuilder; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import org.apache.shenyu.plugin.jwt.exception.ThrowingFunction; +import org.apache.shenyu.spi.Join; + +import java.util.Map; + +@Join +public class DefaultJwtPayloadParseStrategy implements JwtPayloadParseStrategy { + + @Override + public Map parse(final String secretKey, final String authorization) { + JwtParserBuilder jwtParserBuilder = Jwts.parser(); + jwtParserBuilder.verifyWith(Keys.hmacShaKeyFor(secretKey.getBytes())); + JwtParser jwtParser = jwtParserBuilder.build(); + if (jwtParser.isSigned(authorization)) { + Jwt jwt = ThrowingFunction.wrap(() -> jwtParser.parse(authorization)); + return jwt == null ? null : (Map) jwt.getPayload(); + } + return null; + } +} \ No newline at end of file diff --git a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtPayloadParseStrategy.java b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtPayloadParseStrategy.java new file mode 100644 index 000000000000..49737bc551f0 --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtPayloadParseStrategy.java @@ -0,0 +1,39 @@ +/* + * 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.spi.SPI; + +import java.util.Map; + +/** + * Strategy Class for Parsing JWT Payloads. + */ +@SPI +public interface JwtPayloadParseStrategy { + + /** + * Parse jwt payload. + * + * @param secretKey secretKey of authorization + * @param authorization the authorization after processing + * @return Map + */ + Map parse(String secretKey, String authorization); + +} diff --git a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtPayloadParseStrategyFactory.java b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtPayloadParseStrategyFactory.java new file mode 100644 index 000000000000..98548f9cbd6b --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/java/org/apache/shenyu/plugin/jwt/strategy/JwtPayloadParseStrategyFactory.java @@ -0,0 +1,39 @@ +/* + * 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 JwtPayloadParseStrategyFactory { + + /** + * new instance JwtPayloadParserStrategy. + * + * @param handleType handleType + * @return JwtPayloadParserStrategy + */ + public static JwtPayloadParseStrategy newInstance(final String handleType) { + String type = handleType; + if (StringUtils.isBlank(type)) { + type = "default"; + } + return ExtensionLoader.getExtensionLoader(JwtPayloadParseStrategy.class).getJoin(type); + } + +} diff --git a/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtPayloadParseStrategy b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtPayloadParseStrategy new file mode 100644 index 000000000000..a9877bd36397 --- /dev/null +++ b/shenyu-plugin/shenyu-plugin-security/shenyu-plugin-jwt/src/main/resources/META-INF/shenyu/org.apache.shenyu.plugin.jwt.strategy.JwtPayloadParseStrategy @@ -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.DefaultJwtPayloadParseStrategy \ No newline at end of file