一,實現思路
1,基于JWT令牌登陸方式
- JWT實現登錄的,登錄信息就保存在請求頭的token中。因此要獲取當前登錄用戶,只要獲取請求頭,解析其中的token。
1),Gateway網關攔截,解析用戶信息
- 我們的把token解析的行為放到了網關中,然后由網關把用戶信息放入請求頭,傳遞給下游微服務。
- 在Gateway網關中創建一個Filter,攔截并解析JWT,將用戶消息放入請求頭中
-
@Component public class AccountAuthFilter implements GlobalFilter, Ordered {private final AuthUtil authUtil;private final AuthProperties authProperties;private final AntPathMatcher antPathMatcher = new AntPathMatcher();public AccountAuthFilter(AuthUtil authUtil, AuthProperties authProperties) {this.authUtil = authUtil;this.authProperties = authProperties;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1.獲取請求request信息ServerHttpRequest request = exchange.getRequest();String method = request.getMethodValue();String path = request.getPath().toString();String antPath = method + ":" + path;// 2.判斷是否是無需登錄的路徑if(isExcludePath(antPath)){// 直接放行return chain.filter(exchange);}// 3.嘗試獲取用戶信息List<String> authHeaders = exchange.getRequest().getHeaders().get(AUTHORIZATION_HEADER);String token = authHeaders == null ? "" : authHeaders.get(0);R<LoginUserDTO> r = authUtil.parseToken(token);// 4.如果用戶是登錄狀態,嘗試更新請求頭,傳遞用戶信息if(r.success()){exchange.mutate().request(builder -> builder.header(自定義請求頭名稱, r.getData().getUserId().toString())).build();}// 6.放行return chain.filter(exchange);}private boolean isExcludePath(String antPath) {for (String pathPattern : authProperties.getExcludePath()) {if(antPathMatcher.match(pathPattern, antPath)){return true;}}return false;}@Overridepublic int getOrder() {return 1000;} }
2),微服務獲取用戶信息,并將用戶信息放入ThreadLocal中
每個微服務都定義一個Filter,獲取用戶信息。并使用ThreadLocal 將用戶信息放入ThreadLocal中,每個微服務都定義很麻煩,所以我們將Filter抽取出來。
@Slf4j
public class UserInfoInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.嘗試獲取頭信息中的用戶信息String authorization = request.getHeader(請求頭名稱);// 2.判斷是否為空 因為很多微服務不需要獲取用戶信息我們不需要攔截if (authorization == null) {return true;}// 3.轉為用戶id并保存try {Long userId = Long.valueOf(authorization);UserContext.setUser(userId);return true;} catch (NumberFormatException e) {log.error("用戶身份信息格式不正確,{}, 原因:{}", authorization, e.getMessage());return true;}}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清理用戶信息UserContext.removeUser();}
}
?