SpringCloud OpenFeign对接多个系统需要设置多个token时

在使用feign调用远程服务接口时,如果需要携带token,官方推荐的方法是使用设置拦截器,实现RequestInterceptor接口,拦截器可以拦截所有feign请求,在拦截器中编辑header,获取请求头中的token信息,设置到header里面。

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

/**
 * Feign配置
 * 使用FeignClient进行服务间调用,传递headers信息
 */
@Configuration
public class FeignConfig implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //添加token
        requestTemplate.header("Access-Token", request.getHeader("Access-Token"));
    }
}

这种方法可以统一管理token,适用于token来自前端的情况。而且只能设置一个拦截器,设置两个拦截器的话,两个拦截器会同时生效,也没有设置白名单的说法,所以在请求发送的时候,会产生一个status 400 Reading的错误。我的需求,一个模块中对接多个系统的接口,每个系统的接口都有其对应的token获取方法,而不是统一适配同一个token。还好feign还提供了另一个设置token的方式,就是在feign中使用@RequestHeader注解,对每一个feign进行单独的设置

@FeignClient(name = "DmAppearance",url = "https://foas9we.com/"})
public interface DmAppearanceFeign {
    /**
     *  获取基础数据
     * @param appearanceVO
     * @return
     */
    @PostMapping(value = "/api/services/showBaseData",consumes = MediaType.APPLICATION_JSON_VALUE )
    String getAndSave(@RequestBody Map appearanceVO,
                      @RequestHeader(name="Authorization")String token);


}

在调用时就可以作为参数将token传入了

String message = dmAppearanceFeign.getAndSave(appearanceVO,token);

那么token有怎么获取跟保存呢?在这里我使用的是redis设置有效时间参数的形式对token进行保存,发送请求前先从redis中获取token,如果token已经过期失效了,或者还没存入redis中,就调用feign获取接口token
SpringBoot整合Redis及Redis工具类撰写 - zeng1994 - 博客园SpringBoot整合Redis的博客很多,但是很多都不是我想要的结果。因为我只需要整合完成后,可以操作Redis就可以了,并不需要配合缓存相关的注解使用(如@Cacheable)。看了很多博客后,https://www.cnblogs.com/zeng1994/p/03303c805731afc9aa9c60dbbd32a323.html

String token = redisUtils.get("authorizationApprearance")+"";
//reids中没有token信息,或者token已经失效了就重新获取
if(!redisUtils.hasKey("authorizationApprearance")||"".equals(token)||null==token){
                        //通过调用feign,获取到token信息
    RequestTokenVO tokenVO = new RequestTokenVO("123",
        "123",
        "clientForBigDataApi",
        "secret",
        "apiForGreeMesBigDataPermission offline_access",
        "password");
    //获取token
    String msg = dmAppearanceTokenFeign.getAppearanceToken(map);
    AppearanceTokenMsg appearanceTokenMsg = 
    JSONArray.parseObject(msg,AppearanceTokenMsg.class);
    token = "Bearer "+appearanceTokenMsg.getAccess_token();
    //将token交给reids管理,设置有效时间为15分钟
    redisUtils.set("authorizationApprearance",token,900L);
}
//首次查询,在循环之前,以获取总记录数,确认循环次数
String message = dmAppearanceFeign.getAndSave(appearanceVO,token);

这样就完成了对接多个接口需要配置不同token的问题了

另一个想法——统一拦截,分类处理

通过配置RequestInterceptor拦截器,拦截所有的feign请求,然后获取请求的url信息,也就是可以获取到controller的信息比如base/getToken这种,通过逐个匹配的方式对token进行设置

你可能感兴趣的:(java,redis,restful,token,feign)