登录用户信息获取 网关+拦截器+feign请求添加请求头

给所有请求添加用户身份

微服务获取用户身份

网关已经给所有请求添加了用户身份,也就是authorization头信息。

创建ThreadLocal工具类 :

package com.hmall.order.utils;

public class UserHolder {
    private static final ThreadLocal<Long> tl = new ThreadLocal<>();

    public static void setUser(Long userId) {
        tl.set(userId);
    }

    public static Long getUser() {
        return tl.get();
    }

    public static void removeUser() {
        tl.remove();
    }
}

创建拦截器:

package com.hmall.order.interceptor;

import com.hmall.order.utils.UserHolder;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@slf4j
public class UserInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取请求头
        String authorization = request.getHeader("authorization");
        if (StringUtils.isBlank(authorization)) {
         
         log.warn("非法用户访问!请求路径:{}",request.getRequestURI());
            //没有用户信息,未登录
            throw new RuntimeException("用户未登录");            
            //或者 return false; response.setStatus(403);
        }
        //2.转换用户id
        Long userId = Long.valueOf(authorization);
        //3.存入ThreadLocal
        UserHolder.setUser(userId);
        //4.放行
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //用完清理掉
        UserHolder.removeUser();
    }
}

将拦截器注册到SpringMvc,让它生效:

package com.hmall.order.config;

import com.hmall.order.interceptor.UserInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //默认的拦截路径就是/**  ,excludePathPatterns()是不用拦截的路径
//      registry.addInterceptor(new UserInterceptor()).addPathPatterns("/**").excludePathPatterns();
      registry.addInterceptor(new UserInterceptor());
    }
}

将以上代码(拦截器,config,utils) 放到哪个微服务中,哪个微服务/**路径就会有拦截功能

没有用户信息的请求将会被拦截

给所有有feign的请求,将用户信息添加请求头:

package com.hmall.order.config;

import feign.RequestInterceptor;
import feign.RequestTemplate;

public class MyFeignInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header("authorization","2");
    }
}

配置好后通过路径访问的将被拦截,但是通过网关的就可以访问:

被拦截

可访问

如果想不从网关,实现服务之间调用服务, 将controller层的 被调用的方法开放一个接口到feign.

然后再调用者的启动类添加 :上面的包路径要填写一致

注:(记得导feign的包到服务的pom.xml中)

这样因为feign请求头有用户信息通过feign之间调用服务就不会收拦截

经验分享 程序员 微信小程序 职场和发展