Sfoglia il codice sorgente

网关白名单放入nacos配置&支持模糊匹配

RuoYi 5 anni fa
parent
commit
dbadce31c6

+ 119 - 0
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/StringUtils.java

@@ -1,6 +1,7 @@
1 1
 package com.ruoyi.common.core.utils;
2 2
 
3 3
 import java.util.Collection;
4
+import java.util.List;
4 5
 import java.util.Map;
5 6
 import com.ruoyi.common.core.text.StrFormatter;
6 7
 
@@ -17,6 +18,9 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
17 18
     /** 下划线 */
18 19
     private static final char SEPARATOR = '_';
19 20
 
21
+    /** 星号 */
22
+    private static final String START = "*";
23
+
20 24
     /**
21 25
      * 获取参数不为空值
22 26
      * 
@@ -396,6 +400,121 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
396 400
         return sb.toString();
397 401
     }
398 402
 
403
+    /**
404
+     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
405
+     * 
406
+     * @param str 指定字符串
407
+     * @param strs 需要检查的字符串数组
408
+     * @return 是否匹配
409
+     */
410
+    public static boolean matches(String str, List<String> strs)
411
+    {
412
+        if (isEmpty(str) || isEmpty(strs))
413
+        {
414
+            return false;
415
+        }
416
+        for (String testStr : strs)
417
+        {
418
+            if (matches(str, testStr))
419
+            {
420
+                return true;
421
+            }
422
+        }
423
+        return false;
424
+    }
425
+
426
+    /**
427
+     * 查找指定字符串是否匹配指定字符串数组中的任意一个字符串
428
+     * 
429
+     * @param str 指定字符串
430
+     * @param strs 需要检查的字符串数组
431
+     * @return 是否匹配
432
+     */
433
+    public static boolean matches(String str, String... strs)
434
+    {
435
+        if (isEmpty(str) || isEmpty(strs))
436
+        {
437
+            return false;
438
+        }
439
+        for (String testStr : strs)
440
+        {
441
+            if (matches(str, testStr))
442
+            {
443
+                return true;
444
+            }
445
+        }
446
+        return false;
447
+    }
448
+
449
+    /**
450
+     * 查找指定字符串是否匹配
451
+     * 
452
+     * @param str 指定字符串
453
+     * @param pattern 需要检查的字符串
454
+     * @return 是否匹配
455
+     */
456
+    public static boolean matches(String str, String pattern)
457
+    {
458
+        if (isEmpty(pattern) || isEmpty(str))
459
+        {
460
+            return false;
461
+        }
462
+
463
+        pattern = pattern.replaceAll("\\s*", ""); // 替换空格
464
+        int beginOffset = 0; // pattern截取开始位置
465
+        int formerStarOffset = -1; // 前星号的偏移位置
466
+        int latterStarOffset = -1; // 后星号的偏移位置
467
+
468
+        String remainingURI = str;
469
+        String prefixPattern = "";
470
+        String suffixPattern = "";
471
+
472
+        boolean result = false;
473
+        do
474
+        {
475
+            formerStarOffset = indexOf(pattern, START, beginOffset);
476
+            prefixPattern = substring(pattern, beginOffset, formerStarOffset > -1 ? formerStarOffset : pattern.length());
477
+
478
+            // 匹配前缀Pattern
479
+            result = remainingURI.contains(prefixPattern);
480
+            // 已经没有星号,直接返回
481
+            if (formerStarOffset == -1)
482
+            {
483
+                return result;
484
+            }
485
+
486
+            // 匹配失败,直接返回
487
+            if (!result)
488
+                return false;
489
+
490
+            if (!isEmpty(prefixPattern))
491
+            {
492
+                remainingURI = substringAfter(str, prefixPattern);
493
+            }
494
+
495
+            // 匹配后缀Pattern
496
+            latterStarOffset = indexOf(pattern, START, formerStarOffset + 1);
497
+            suffixPattern = substring(pattern, formerStarOffset + 1, latterStarOffset > -1 ? latterStarOffset : pattern.length());
498
+
499
+            result = remainingURI.contains(suffixPattern);
500
+            // 匹配失败,直接返回
501
+            if (!result)
502
+                return false;
503
+
504
+            if (!isEmpty(suffixPattern))
505
+            {
506
+                remainingURI = substringAfter(str, suffixPattern);
507
+            }
508
+
509
+            // 移动指针
510
+            beginOffset = latterStarOffset + 1;
511
+
512
+        }
513
+        while (!isEmpty(suffixPattern) && !isEmpty(remainingURI));
514
+
515
+        return true;
516
+    }
517
+
399 518
     @SuppressWarnings("unchecked")
400 519
     public static <T> T cast(Object obj)
401 520
     {

+ 33 - 0
ruoyi-gateway/src/main/java/com/ruoyi/gateway/config/properties/IgnoreWhiteProperties.java

@@ -0,0 +1,33 @@
1
+package com.ruoyi.gateway.config.properties;
2
+
3
+import java.util.ArrayList;
4
+import java.util.List;
5
+import org.springframework.boot.context.properties.ConfigurationProperties;
6
+import org.springframework.cloud.context.config.annotation.RefreshScope;
7
+import org.springframework.context.annotation.Configuration;
8
+
9
+/**
10
+ * 放行白名单配置
11
+ * 
12
+ * @author ruoyi
13
+ */
14
+@Configuration
15
+@RefreshScope
16
+@ConfigurationProperties(prefix = "ignore")
17
+public class IgnoreWhiteProperties
18
+{
19
+    /**
20
+     * 放行白名单配置,网关不校验此处的白名单
21
+     */
22
+    private List<String> whites = new ArrayList<>();
23
+
24
+    public List<String> getWhites()
25
+    {
26
+        return whites;
27
+    }
28
+
29
+    public void setWhites(List<String> whites)
30
+    {
31
+        this.whites = whites;
32
+    }
33
+}

+ 7 - 6
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java

@@ -1,9 +1,9 @@
1 1
 package com.ruoyi.gateway.filter;
2 2
 
3
-import java.util.Arrays;
4 3
 import javax.annotation.Resource;
5 4
 import org.slf4j.Logger;
6 5
 import org.slf4j.LoggerFactory;
6
+import org.springframework.beans.factory.annotation.Autowired;
7 7
 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
8 8
 import org.springframework.cloud.gateway.filter.GlobalFilter;
9 9
 import org.springframework.core.Ordered;
@@ -20,6 +20,7 @@ import com.alibaba.fastjson.JSONObject;
20 20
 import com.ruoyi.common.core.constant.CacheConstants;
21 21
 import com.ruoyi.common.core.domain.R;
22 22
 import com.ruoyi.common.core.utils.StringUtils;
23
+import com.ruoyi.gateway.config.properties.IgnoreWhiteProperties;
23 24
 import reactor.core.publisher.Mono;
24 25
 
25 26
 /**
@@ -32,9 +33,9 @@ public class AuthFilter implements GlobalFilter, Ordered
32 33
 {
33 34
     private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
34 35
 
35
-    // 排除过滤的 uri 地址,swagger排除自行添加
36
-    private static final String[] whiteList = { "/auth/login", "/code/v2/api-docs", "/schedule/v2/api-docs",
37
-            "/system/v2/api-docs", "/csrf" };
36
+    // 排除过滤的 uri 地址,nacos自行添加
37
+    @Autowired
38
+    private IgnoreWhiteProperties ignoreWhite;
38 39
 
39 40
     @Resource(name = "stringRedisTemplate")
40 41
     private ValueOperations<String, String> sops;
@@ -44,7 +45,7 @@ public class AuthFilter implements GlobalFilter, Ordered
44 45
     {
45 46
         String url = exchange.getRequest().getURI().getPath();
46 47
         // 跳过不需要验证的路径
47
-        if (Arrays.asList(whiteList).contains(url))
48
+        if (StringUtils.matches(url, ignoreWhite.getWhites()))
48 49
         {
49 50
             return chain.filter(exchange);
50 51
         }
@@ -69,7 +70,7 @@ public class AuthFilter implements GlobalFilter, Ordered
69 70
         ServerHttpRequest mutableReq = exchange.getRequest().mutate().header(CacheConstants.DETAILS_USER_ID, userid)
70 71
                 .header(CacheConstants.DETAILS_USERNAME, username).build();
71 72
         ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
72
-        
73
+
73 74
         return chain.filter(mutableExchange);
74 75
     }
75 76
 

File diff suppressed because it is too large
+ 1 - 1
sql/ry_config_20200901.sql