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 }