SpringCloud客户端FeignClient调用时传递Token


前言

Feign是一个声明式WebService客户端。在SpringCloud中可以通过FeignClient来进行服务间的调用。

而为了对API进行权限控制,项目中会进行权限认证,JWT或者Security。这时问题就会出现了,在加了授权认证之后,不管是JWT也好,Security也好,Feign调用总是没有权限。

其实我们知道不管是选择哪种,最终token都是放在请求头里面,访问时携带以通过认证。

可是当使用Feign时就会发现这样一个问题,外部请求到A服务的时候,A服务是可以拿到token(认证信息)的,然而当A使用Feign调用B服务时,token就会丢失,进而认证失败,权限不足。

解决方案

这时候我们需要做的就是在Feign调用的时候,向其请求头里面添加上Token

实现接口RequestInterceptor

假设我们在验证权限的时候放在请求头里面的就叫token,我们先获取当前请求中的token,然后放到Feign的请求头上,当然具体还是要根据自己的业务来,这里就简单实现一下

public class FeignConfigInterceptor implements RequestInterceptor{

    @Value("${jwt.header}")
    private String tokenHeader;
    @Override
    public void apply(RequestTemplate requestTemplate) {
        requestTemplate.header(tokenHeader, getHeaders(getHttpServletRequest()).get(tokenHeader));
    }

    private HttpServletRequest getHttpServletRequest() {
        try {
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        } catch (Exception e) {
            return null;
        }
    }

    private Map<String, String> getHeaders(HttpServletRequest request) {
        Map<String, String> map = new LinkedHashMap<>();
        Enumeration<String> enumeration = request.getHeaderNames();
        while (enumeration.hasMoreElements()) {
            String key = enumeration.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }
}

使用创建的FeignConfigInterceptor

在@FeignClient注解里面的属性加上configuration = FeignConfigInterceptor.class

@FeignClient(name = "user",url = "localhost:8081",configuration = FeignConfigInterceptor.class)
public interface UserServiceClient {

}

这时候再调用就会发现已经携带token了。

插曲

在获取request所有的头信息的时候,使用 request.getHeaderNames()遍历后(即上文的private Map<String String> getHeaders(HttpServletRequest request)方法),其中的key全部为小写。而我定义的tokenHeader是有大小写的,因此任然匹配不上。最后发现,直接使用request.getHeader(String var1)这个方法就可以获取到值。

最后

其实实现了RequestInterceptor后,直接使用@Configuration注解,不在FeignClient里面加属性也是可以的。


文章作者: Niww
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Niww !
 上一篇
SpringBoot下前后台分离时间处理 SpringBoot下前后台分离时间处理
之前在前后端交互过程中,针对时间类型的字段,在DTO中使用String类型接收,在后台转成Date类型。但这样处理太麻烦。JDK8的新特性中Time API,其包括Clock、Duration、Instant、LocalDate、Loca
2018-04-24
下一篇 
Win7 环境安装RabbitMQ Win7 环境安装RabbitMQ
在Windows环境下安装RabbitMQ时遇到了一个坑,当启动服务时(``rabbitmq-service start`),出现一串乱码错误,原因是需要以管理员身份运行cmd命令窗口。 安装步骤 RabbitMQ依赖erlang,所以先
2018-03-25
  目录