Spring微服务OpenFeign调用时,下游服务无法获取token中的用户信息

情景描述:
一个网关Gateway,一个微服务A,一个微服务B

  • 网关服务中配置了路由规则
        - id: serviceA
          uri: lb://A-service
          predicates:
            - Path=/A/**
        - id: serviceB
          uri: lb://B-service
          predicates:
            - Path=/B/**

当需要访问服务A和服务B,都会经过网关。

  • 网关中有全局过滤器Globalfilter
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String string = request.getPath().toString();
        if(isExclude(string)){
            return chain.filter(exchange);
        }

        String token=null;
        List<String> authorlization = request.getHeaders().get("authorization");

        if(authorlization!=null&&!authorlization.isEmpty()){
            token = authorlization.get(0);
        }

        Long l=null;
        try {

          userID = jwtTool.parseToken(token);

            Long finalid = userID;
            ServerHttpRequest uid = request.mutate().headers(h -> {
                h.add("uid", finalid.toString());
            }).build();

            exchange.mutate().request(uid).build();

        } catch (Exception e) {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }



        return chain.filter(exchange);
    }

网关过滤器往request中加入了userId
之后的微服务可以通过自定义拦截器userInterceptor获取这个userId来用于各个业务;

private static final ThreadLocal<Long> tl = new ThreadLocal<>();
public class userInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uid = request.getHeader("uid");
        Long l = Long.valueOf(uid);
        tl.set(l);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        tl.remove();
    }
}

之后的微服务通过tl.get()获得userId;

这里都没有什么问题,
但当微服务A通过OpenFeignFeignClient调用微服务B时,如果微服务B某个业务需要用到userId时,会发现通过ThreadLocal中的用户id是空的!!!

找了好久,发现是由于通过feign调用另一个微服务时,它的线程可能是变了,好像叫feign熔断机制

通过关闭它,

feign:
  hystrix:
    enabled: false

这样调用另一个微服务时ThreadLocal中的userId就不为空了。

参考Feign调用服务Session失效问题以及使用RequestContextHolder.getRequestAttributes()获取值为null的问题 还有几种方法。

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值