zoukankan      html  css  js  c++  java
  • Spring Cloud中Feign如何统一设置验证token

    代码地址:https://github.com/hbbliyong/springcloud.git

    原理是通过每个微服务请求之前都从认证服务获取认证之后的token,然后将token放入到请求头中带过去,这样被调用方通过验证token来判断是否合法请求

    我们也在zuul中通过前置过滤器来统一设置token, 其实还漏掉了一种,那就是业务服务调用业务服务的时候,是没有zuul这种前置过滤器的,那么我们该如何设置呢?

    其实也挺简单的,因为我们服务之前的调用是依赖于Feign的,我们可以从Feign上来做文章

    如果你仔细看过Feign的文档的话,肯定会注意到下面一段代码:

    tatic class DynamicAuthTokenTarget<T> implements Target<T> {
    public DynamicAuthTokenTarget(Class<T> clazz,
    UrlAndTokenProvider provider,
    ThreadLocal<String> requestIdProvider);
    ...
    @Override
    public Request apply(RequestTemplate input) {
    TokenIdAndPublicURL urlAndToken = provider.get();
    if (input.url().indexOf("http") != 0) {
    input.insert(0, urlAndToken.publicURL);
    }
    input.header("X-Auth-Token", urlAndToken.tokenId);
    input.header("X-Request-ID", requestIdProvider.get());
    
    return input.request();
    }
    }
    ...
    Bank bank = Feign.builder()
    .target(new DynamicAuthTokenTarget(Bank.class, provider, requestIdProvider));
    

      


    我们可以为Feign设置一个请求拦截器,在调用之前做一些事情,添加请求头信息

    原生的Feign都能添加拦截器,Spring Cloud中那肯定也是可以的

    前面的文章中我们讲过通过自定义配置来覆盖默认配置,我们创建了一个FeignConfiguration配置类来配置Feign的日志

    今天终于又派上用场了, 可以在这边自定义一个拦截器

    @Configuration
    public class FeignConfiguration {
    /**
    * 日志级别
    * @return
    */
    @Bean 
    Logger.Level feignLoggerLevel() { 
    return Logger.Level.FULL; 
    }
    
    /**
    * 创建Feign请求拦截器,在发送请求前设置认证的token,各个微服务将token设置到环境变量中来达到通用
    * @return
    */
    @Bean
    public FeignBasicAuthRequestInterceptor basicAuthRequestInterceptor() {
    return new FeignBasicAuthRequestInterceptor();
    }
    
    }
    
    /**
    * Feign请求拦截器
    * @author yinjihuan
    * @create 2017-11-10 17:25
    **/
    public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
    
    public FeignBasicAuthRequestInterceptor() {
    
    }
    
    @Override
    public void apply(RequestTemplate template) {
    template.header("Authorization", System.getProperty("fangjia.auth.token"));
    }
    }
    

      

    大致的步骤呢就是通过设置Feign的拦截器来设置token, 因为这边是通用的,所有呢token的值通过环境变量来传递

    每个微服务只需要将获取的token信息设置到环境变量中即可

    System.setProperty("fangjia.auth.token", token);

    上次我们也讲过如果来自动获取token,我们是通过定时任务来定时刷新的,当时还创建了AuthService来获取token

    今天在优化下,因为这个也需要通用,所以直接将Service去掉了

    /**
    * 定时刷新token
    *
    * @author yinjihuan
    * @create 2017-11-09 15:39
    **/
    @Component
    public class TokenScheduledTask {
    private static Logger logger = LoggerFactory.getLogger(TokenScheduledTask.class);
    
    public final static long ONE_Minute = 60 * 1000 * 60 * 20;
    
    @Autowired
    private AuthRemoteClient authRemoteClient;
    
    /**
    * 刷新Token
    */
    @Scheduled(fixedDelay = ONE_Minute)
    public void reloadApiToken() {
    String token = this.getToken();
    while (StringUtils.isBlank(token)) {
    try {
    Thread.sleep(1000);
    token = this.getToken();
    } catch (InterruptedException e) {
    logger.error("", e);
    }
    }
    System.setProperty("fangjia.auth.token", token);
    }
    
    public String getToken() {
    AuthQuery query = new AuthQuery();
    query.setAccessKey("1");
    query.setSecretKey("1");
    ResponseData response = authRemoteClient.auth(query);
    return response.getData() == null ? "" : response.getData().toString();
    }
    }
    

      

    到现在,各个微服务直接的安全认证就结束啦,用起来不麻烦,下面总结下

    定义一个用于认证的微服务,可以有用户信息,和业务无关,提供认证接口
    定义JWT工具类,提供生成token和检查token的方法,公用
    定义认证token的过滤器,公用
    在需要认证的微服务中注册过滤器即可实现拦截操作, 也可做成公用的,就是所有都需要认证
    在调用方配置TokenScheduledTask,实现定时刷新token, 也可做成公用的
    如果不需要认证,那么不注册拦截过滤器即可,也不用 TokenScheduledTask,对业务代码无任何倾入性

  • 相关阅读:
    Single Number II
    Pascal's Triangle
    Remove Duplicates from Sorted Array
    Populating Next Right Pointers in Each Node
    Minimum Depth of Binary Tree
    Unique Paths
    Sort Colors
    Swap Nodes in Pairs
    Merge Two Sorted Lists
    Climbing Stairs
  • 原文地址:https://www.cnblogs.com/smiler/p/10690303.html
Copyright © 2011-2022 走看看