RuoYi
2020-09-13 dbadce31c6fa6038423dab044cf5209677dbf132
网关白名单放入nacos配置&支持模糊匹配
1 files added
1 files renamed
2 files modified
167 ■■■■■ changed files
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java 119 ●●●●● patch | view | raw | blame | history
ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java 33 ●●●●● patch | view | raw | blame | history
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java 13 ●●●● patch | view | raw | blame | history
sql/ry_config_20200913.sql 2 ●●● patch | view | raw | blame | history
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)
    {
ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java
New file
@@ -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;
    }
}
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);
    }
sql/ry_config_20200913.sql
File was renamed from sql/ry_config_20200901.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'),