From dbadce31c6fa6038423dab044cf5209677dbf132 Mon Sep 17 00:00:00 2001
From: RuoYi <yzz_ivy@163.com>
Date: Sun, 13 Sep 2020 12:00:46 +0800
Subject: [PATCH] 网关白名单放入nacos配置&支持模糊匹配
---
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java | 119 +++++++++++++++++++++++++++++++++++++++
sql/ry_config_20200913.sql | 2
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java | 13 ++--
ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java | 33 +++++++++++
4 files changed, 160 insertions(+), 7 deletions(-)
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java
index a0d0c91..e0bc15a 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java
@@ -1,6 +1,7 @@
package com.ruoyi.common.core.utils;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
import com.ruoyi.common.core.text.StrFormatter;
@@ -16,6 +17,9 @@
/** 下划线 */
private static final char SEPARATOR = '_';
+
+ /** 星号 */
+ private static final String START = "*";
/**
* 获取参数不为空值
@@ -396,6 +400,121 @@
return sb.toString();
}
+ /**
+ * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
+ *
+ * @param str 指定字符串
+ * @param strs 需要检查的字符串数组
+ * @return 是否匹配
+ */
+ public static boolean matches(String str, List<String> strs)
+ {
+ if (isEmpty(str) || isEmpty(strs))
+ {
+ return false;
+ }
+ for (String testStr : strs)
+ {
+ if (matches(str, testStr))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 查找指定字符串是否匹配指定字符串数组中的任意一个字符串
+ *
+ * @param str 指定字符串
+ * @param strs 需要检查的字符串数组
+ * @return 是否匹配
+ */
+ public static boolean matches(String str, String... strs)
+ {
+ if (isEmpty(str) || isEmpty(strs))
+ {
+ return false;
+ }
+ for (String testStr : strs)
+ {
+ if (matches(str, testStr))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 查找指定字符串是否匹配
+ *
+ * @param str 指定字符串
+ * @param pattern 需要检查的字符串
+ * @return 是否匹配
+ */
+ public static boolean matches(String str, String pattern)
+ {
+ if (isEmpty(pattern) || isEmpty(str))
+ {
+ return false;
+ }
+
+ pattern = pattern.replaceAll("\\s*", ""); // 替换空格
+ int beginOffset = 0; // pattern截取开始位置
+ int formerStarOffset = -1; // 前星号的偏移位置
+ int latterStarOffset = -1; // 后星号的偏移位置
+
+ String remainingURI = str;
+ String prefixPattern = "";
+ String suffixPattern = "";
+
+ boolean result = false;
+ do
+ {
+ formerStarOffset = indexOf(pattern, START, beginOffset);
+ prefixPattern = substring(pattern, beginOffset, formerStarOffset > -1 ? formerStarOffset : pattern.length());
+
+ // 匹配前缀Pattern
+ result = remainingURI.contains(prefixPattern);
+ // 已经没有星号,直接返回
+ if (formerStarOffset == -1)
+ {
+ return result;
+ }
+
+ // 匹配失败,直接返回
+ if (!result)
+ return false;
+
+ if (!isEmpty(prefixPattern))
+ {
+ remainingURI = substringAfter(str, prefixPattern);
+ }
+
+ // 匹配后缀Pattern
+ latterStarOffset = indexOf(pattern, START, formerStarOffset + 1);
+ suffixPattern = substring(pattern, formerStarOffset + 1, latterStarOffset > -1 ? latterStarOffset : pattern.length());
+
+ result = remainingURI.contains(suffixPattern);
+ // 匹配失败,直接返回
+ if (!result)
+ return false;
+
+ if (!isEmpty(suffixPattern))
+ {
+ remainingURI = substringAfter(str, suffixPattern);
+ }
+
+ // 移动指针
+ beginOffset = latterStarOffset + 1;
+
+ }
+ while (!isEmpty(suffixPattern) && !isEmpty(remainingURI));
+
+ return true;
+ }
+
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj)
{
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java
new file mode 100644
index 0000000..fbfd04c
--- /dev/null
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java
@@ -0,0 +1,33 @@
+package com.ruoyi.gateway.config.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 放行白名单配置
+ *
+ * @author ruoyi
+ */
+@Configuration
+@RefreshScope
+@ConfigurationProperties(prefix = "ignore")
+public class IgnoreWhiteProperties
+{
+ /**
+ * 放行白名单配置,网关不校验此处的白名单
+ */
+ private List<String> whites = new ArrayList<>();
+
+ public List<String> getWhites()
+ {
+ return whites;
+ }
+
+ public void setWhites(List<String> whites)
+ {
+ this.whites = whites;
+ }
+}
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
index d1c26b6..a92bb19 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
@@ -1,9 +1,9 @@
package com.ruoyi.gateway.filter;
-import java.util.Arrays;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
@@ -20,6 +20,7 @@
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties;
import reactor.core.publisher.Mono;
/**
@@ -32,9 +33,9 @@
{
private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
- // 排除过滤的 uri 地址,swagger排除自行添加
- private static final String[] whiteList = { "/auth/login", "/code/v2/api-docs", "/schedule/v2/api-docs",
- "/system/v2/api-docs", "/csrf" };
+ // 排除过滤的 uri 地址,nacos自行添加
+ @Autowired
+ private IgnoreWhiteProperties ignoreWhite;
@Resource(name = "stringRedisTemplate")
private ValueOperations<String, String> sops;
@@ -44,7 +45,7 @@
{
String url = exchange.getRequest().getURI().getPath();
// 跳过不需要验证的路径
- if (Arrays.asList(whiteList).contains(url))
+ if (StringUtils.matches(url, ignoreWhite.getWhites()))
{
return chain.filter(exchange);
}
@@ -69,7 +70,7 @@
ServerHttpRequest mutableReq = exchange.getRequest().mutate().header(CacheConstants.DETAILS_USER_ID, userid)
.header(CacheConstants.DETAILS_USERNAME, username).build();
ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
-
+
return chain.filter(mutableExchange);
}
diff --git a/sql/ry_config_20200901.sql b/sql/ry_config_20200913.sql
similarity index 96%
rename from sql/ry_config_20200901.sql
rename to sql/ry_config_20200913.sql
index 1752359..d9d37f4 100644
--- a/sql/ry_config_20200901.sql
+++ b/sql/ry_config_20200913.sql
@@ -33,7 +33,7 @@
insert into config_info(id, data_id, group_id, content, md5, gmt_create, gmt_modified, src_user, src_ip, app_name, tenant_id, c_desc, c_use, effect, type, c_schema) values
(1,'application-dev.yml','DEFAULT_GROUP','spring:\n main:\n allow-bean-definition-overriding: true\n\n#请求处理的超时时间\nribbon:\n ReadTimeout: 10000\n ConnectTimeout: 10000\n\n# feign 配置\nfeign:\n sentinel:\n enabled: true\n okhttp:\n enabled: true\n httpclient:\n enabled: false\n client:\n config:\n default:\n connectTimeout: 10000\n readTimeout: 10000\n compression:\n request:\n enabled: true\n response:\n enabled: true\n\n# 暴露监控端点\nmanagement:\n endpoints:\n web:\n exposure:\n include: \'*\'\n','57470c6d167154919418fa150863b7fb','2019-11-29 16:31:20','2020-09-01 09:14:30',NULL,'0:0:0:0:0:0:0:1','','','通用配置','null','null','yaml','null'),
-(2,'ruoyi-gateway-dev.yml','DEFAULT_GROUP','spring:\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n cloud:\r\n gateway:\r\n discovery:\r\n locator:\r\n lowerCaseServiceId: true\r\n enabled: true\r\n routes:\r\n # 认证中心\r\n - id: ruoyi-auth\r\n uri: lb://ruoyi-auth\r\n predicates:\r\n - Path=/auth/**\r\n filters:\r\n # 验证码处理\r\n - CacheRequestFilter\r\n - ValidateCodeFilter\r\n - StripPrefix=1\r\n # 代码生成\r\n - id: ruoyi-gen\r\n uri: lb://ruoyi-gen\r\n predicates:\r\n - Path=/code/**\r\n filters:\r\n - StripPrefix=1\r\n # 定时任务\r\n - id: ruoyi-job\r\n uri: lb://ruoyi-job\r\n predicates:\r\n - Path=/schedule/**\r\n filters:\r\n - StripPrefix=1\r\n # 系统模块\r\n # 系统模块\r\n - id: ruoyi-system\r\n uri: lb://ruoyi-system\r\n predicates:\r\n - Path=/system/**\r\n filters:\r\n - name: BlackListUrlFilter\r\n args:\r\n blacklistUrl:\r\n - /user/info/*\r\n - StripPrefix=1\r\n','1c11e0d5e5e4f983f378088740102540','2020-05-14 14:17:55','2020-08-31 20:30:38',NULL,'0:0:0:0:0:0:0:1','','','网关模块','null','null','yaml','null'),
+(2,'ruoyi-gateway-dev.yml','DEFAULT_GROUP','spring:\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n cloud:\r\n gateway:\r\n discovery:\r\n locator:\r\n lowerCaseServiceId: true\r\n enabled: true\r\n routes:\r\n # 认证中心\r\n - id: ruoyi-auth\r\n uri: lb://ruoyi-auth\r\n predicates:\r\n - Path=/auth/**\r\n filters:\r\n # 验证码处理\r\n - CacheRequestFilter\r\n - ValidateCodeFilter\r\n - StripPrefix=1\r\n # 代码生成\r\n - id: ruoyi-gen\r\n uri: lb://ruoyi-gen\r\n predicates:\r\n - Path=/code/**\r\n filters:\r\n - StripPrefix=1\r\n # 定时任务\r\n - id: ruoyi-job\r\n uri: lb://ruoyi-job\r\n predicates:\r\n - Path=/schedule/**\r\n filters:\r\n - StripPrefix=1\r\n # 系统模块\r\n - id: ruoyi-system\r\n uri: lb://ruoyi-system\r\n predicates:\r\n - Path=/system/**\r\n filters:\r\n - StripPrefix=1\r\n\r\n# 不校验白名单\r\nignore:\r\n whites:\r\n - /auth/login\r\n - /*/v2/api-docs\r\n - /csrf','842e379b2dfdf0316c020c8dfe2fcb28','2020-05-14 14:17:55','2020-09-13 11:49:19',NULL,'0:0:0:0:0:0:0:1','','','网关模块','null','null','yaml','null'),
(3,'ruoyi-auth-dev.yml','DEFAULT_GROUP','spring: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n','868c15010a7a15c027d4c90a48aabb3e','2020-05-14 13:20:49','2020-06-09 16:30:50',NULL,'0:0:0:0:0:0:0:1','','','认证中心','null','null','yaml','null'),
(4,'ruoyi-monitor-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n security:\r\n user:\r\n name: ruoyi\r\n password: 123456\r\n boot:\r\n admin:\r\n ui:\r\n title: 若依服务状态监控\r\n','8e49d78998a7780d780305aeefe4fb1b','2020-05-19 15:14:01','2020-05-19 18:50:44',NULL,'0:0:0:0:0:0:0:1','','','监控中心','null','null','yaml','null'),
(5,'ruoyi-system-dev.yml','DEFAULT_GROUP','# Spring\r\nspring: \r\n redis:\r\n host: localhost\r\n port: 6379\r\n password: \r\n datasource:\r\n driver-class-name: com.mysql.cj.jdbc.Driver\r\n url: jdbc:mysql://localhost:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8\r\n username: root\r\n password: password\r\n\r\n# Mybatis配置\r\nmybatis:\r\n # 搜索指定包别名\r\n typeAliasesPackage: com.ruoyi.system\r\n # 配置mapper的扫描,找到所有的mapper.xml映射文件\r\n mapperLocations: classpath:mapper/**/*.xml\r\n\r\n# swagger 配置\r\nswagger:\r\n title: 系统模块接口文档\r\n license: Powered By ruoyi\r\n licenseUrl: https://ruoyi.vip\r\n authorization:\r\n name: RuoYi OAuth\r\n auth-regex: ^.*$\r\n authorization-scope-list:\r\n - scope: server\r\n description: 客户端授权范围\r\n token-url-list:\r\n - http://localhost:8080/auth/oauth/token\r\n','06f95c879d284ec8031cc44805e62b50','2020-05-14 13:37:04','2020-07-02 20:03:46',NULL,'0:0:0:0:0:0:0:1','','','系统模块','null','null','yaml','null'),
--
Gitblit v1.9.3