• Feign的异步调用或者MQ调用与Security的问题处理;


    两大踩坑点:

      一:部分框架自带有查询当前登录人的信息工具,无需各种本地线程栈ThreadLocals取Request啥的折磨自己;

      二:Security自带有uri匹配的工具,没事多翻翻源码,原创方法的执行效率可能并不高;

      1 package com.*.server.order.config;
      2 
      3 import com.*.common.core.utils.*Util;
      4 import com.*.common.core.utils.StringUtils;
      5 import com.*.common.redis.service.RedisService;
      6 import com.*.common.security.starter.configure.*CloudResourceServerConfigure;
      7 import com.*.common.security.starter.properties.*CloudSecurityProperties;
      8 import feign.RequestInterceptor;
      9 import feign.RequestTemplate;
     10 import lombok.extern.slf4j.Slf4j;
     11 import org.springframework.beans.factory.annotation.Autowired;
     12 import org.springframework.context.annotation.Configuration;
     13 import org.springframework.core.annotation.Order;
     14 import org.springframework.util.AntPathMatcher;
     15 import org.springframework.util.ObjectUtils;
     16 
     17 import java.lang.reflect.Field;
     18 import java.util.*;
     19 import java.util.concurrent.atomic.AtomicBoolean;
     20 
     21 /**
     22  * 功能描述:Feign调用异常
     23  *
     24  * @author 唐泽齐
     25  */
     26 @Slf4j
     27 @Configuration
     28 @Order(Integer.MAX_VALUE)
     29 public class FeignConfiguration implements RequestInterceptor {
     30 
     31     @Autowired
     32     private RedisService redisService;
     33     private static String[] patterns;
     34 
     35     @Autowired
     36     public void init(*CloudResourceServerConfigure *CloudResourceServerConfigure) {
     37         try {
     38             log.warn("初始化FeignConfiguration");
     39             Field field = *CloudResourceServerConfigure.class.getDeclaredField("properties");
     40             field.setAccessible(true);
     41             *CloudSecurityProperties properties = (*CloudSecurityProperties) field.get(*CloudResourceServerConfigure);
     42             patterns = properties.getAnonUris().split(",");
     43         } catch (Exception e) {
     44             patterns = new String[]{};
     45         }
     46     }
     47 
     48     @Override
     49     public void apply(RequestTemplate template) {
     50         Map<String, Collection<String>> headers = template.headers();
     51         String currentTokenValue = *Util.getCurrentTokenValue();
     52         if (StringUtils.isEmpty(currentTokenValue) && !checkLogin(template.url())) {
     53             log.info("为" + template.url() + "填充Token:" + redisService.get("admin_token"));
     54             template.header("Authorization", "bearer " + redisService.get("admin_token"));
     55             template.header("GatewayToken", Collections.singleton("bGVjaHVhbmc6Z2F0ZXdheToxMjM0NTY="));
     56         }
     57     }
     58 
     59     //判断当前请求是否本身就不需要登录
     60     private boolean checkLogin(String uri) {
     61         if (ObjectUtils.isEmpty(patterns)) {
     62             return false;
     63         }
     64 
     65         //创建uri新对象
     66         String finalUri = uri + "";
     67         //补充 “/”
     68         if (!uri.startsWith("/")) {
     69             finalUri += "/";
     70         }
     71         // 过滤 “?”之后的
     72         if (uri.indexOf("?") >= 0) {
     73             finalUri = finalUri.substring(0, finalUri.indexOf("?"));
     74         }
     75         // 原子化 返回结果
     76         AtomicBoolean mustLogin = new AtomicBoolean(false);
     77         String finalUri1 = finalUri;
     78         // 另开 方法,增加 逃逸度
     79         Arrays.stream(patterns).forEach(p -> {
     80             //使用 AntPathMatcher 检查
     81             if (new AntPathMatcher().match(p, uri)) {
     82                 mustLogin.set(true);
     83                 return;
     84             }
     85 //                //自己写检验方法
     86 //                if(!doCheck(p,finalUri1)) {
     87 //                    mustLogin.set(true);
     88 //                    return;
     89 //                };
     90         });
     91         return mustLogin.get();
     92     }
     93 
     94     private boolean doCheck(String check, String uri) {
     95         //是否忽略登录
     96         boolean result = true;
     97         try {
     98             Iterator<String> ic = Arrays.stream(check.split("/")).iterator();
     99             Iterator<String> iu = Arrays.stream(uri.split("/")).iterator();
    100             for (; ic.hasNext(); ) {
    101                 if (!iu.hasNext()) {
    102                     result = false;
    103                     break;
    104                 }
    105                 String c = ic.next();
    106                 String u = iu.next();
    107                 // 处理 /**
    108                 if (c.equals("**") && !ic.hasNext()) {
    109                     result = true;
    110                     break;
    111                 }
    112                 // 处理 /*
    113                 if (c.equals("*") && !ic.hasNext() && !iu.hasNext()) {
    114                     result = true;
    115                     break;
    116                 }
    117                 // 处理 /**/
    118                 if (c.equals("**") && ic.hasNext() && iu.hasNext()) {
    119                     String nextp = ic.next();
    120                     while (iu.hasNext()) {
    121                         if (nextp.equals(iu.next())) {
    122                             break;
    123                         }
    124                     }
    125                     continue;
    126                 }
    127                 //处理 /*/
    128                 if (c.equals("*") && ic.hasNext() && iu.hasNext()) {
    129                     continue;
    130                 }
    131                 if (!c.equals(u)) {
    132                     result = false;
    133                     break;
    134                 }
    135             }
    136         } catch (Exception e) {
    137             log.warn("检查异常,过滤当前规则。check:" + check + " ===> uri:" + uri, e);
    138             result = false;
    139         }
    140         return result;
    141     }
    142 
    143 }
    具体代码如下
  • 相关阅读:
    K-Means算法总结
    C#设计模式(1)——单例模式
    sql 建表以及查询---复杂查询之成绩排名
    c# 折半查找法实现代码
    c# 合并两个有序数组
    C#中static void Main(string[] args)的含义
    C#中Main函数为什么要static
    C# 生成订单号的几种方式
    sql for xml path用法
    web端跨域调用webapi
  • 原文地址:https://www.cnblogs.com/tangzeqi/p/15075345.html
Copyright © 2020-2023  润新知