Spring Cloud中如何保证各个微服务之间调用的安全性(下篇)

今天我们继续接着上篇文章来聊一聊如何能够在调用方实现token的自动设置以及刷新。

我们的认证token是放在请求头中的,相对于把token放在请求参数中更为友好,对业务接口无侵入性。

但是这种方式如果需要自己设置token就麻烦了,如果是参数的形式,那么在调用的时候就把获取的token当做参数传就可以了。

House getHouseInfo(Long id, String token);

传参的方式不好的就是每个接口需要增加一个参数的定义:

/**
 * 获取房产信息
 * @param houseId 房产编号
 * @return 
 */
@GetMapping("/{houseId}/{token}")
public ResponseData hosueInfo(@PathVariable("houseId")Long houseId,@PathVariable("token")String token) {
    return ResponseData.ok(houseService.getHouseInfo(houseId));
}

或者下面这种方式:

/**
 * 获取房产信息
 * @param houseId 房产编号
 * @return 
 */
@GetMapping("/")
public ResponseData hosueInfo(Long houseId,String token) {
    return ResponseData.ok(houseService.getHouseInfo(houseId));
}

如果是PathVariable这种方式,参数是必传的,不然无法进入接口内,如果是RequestParam这种方式,方法中不定义token参数,我估计也是可以的,至少不会报错,反正我们是统一的去判断有无权限。

所以说我们的token放在请求头中,是非常友好的一种方式。

接下来我们说说使用的问题

在调用接口的时候怎么往请求头中添加token呢?

每次调用的地方都去添加token是不是太烦了?

其实在Zuul中我们可以用过滤器来统一添加token,这个时候可以使用置前的过滤器pre

**
 * 调用服务前添加认证请求头过滤器
 *
 * @author yinjihuan
 * @create 2017-11-07 16:06
 **/
public class AuthHeaderFilter extends ZuulFilter {
    public AuthHeaderFilter() {
        super();
    }
    @Override
    public boolean shouldFilter() {
        return true;
    }
    @Override
    public String filterType() {
        return "pre";
    }
    @Override
    public int filterOrder() {
        return 0;
    }
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        ctx.addZuulRequestHeader("Authorization", TokenScheduledTask.token);
        return null;
    }
}

这样在每个请求转发到具体的微服务之前,我们给它添加了token信息,这个token信息是我们从TokenScheduledTask获取的

TokenScheduledTask是怎么获取token的呢?

/**
 * 定时刷新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;
    public static String token = "";
    @Autowired
    private AuthService authService;
    /**
     * 刷新Token
     */
    @Scheduled(fixedDelay = ONE_Minute)
    public void reloadApiToken() {
        token = authService.getToken();
        while (StringUtils.isBlank(token)) {
            try {
                Thread.sleep(1000);
                token = authService.getToken();
            } catch (InterruptedException e) {
                logger.error("", e);
            }
        }
    }
}

原来是一个定时任务,通过调用认证的方法来获取认证好的token。

为什么要做成定时的呢

如果按照一般的做法那就是请求之后都去获取一次token, 这种方式是最不好的,性能太差。

稍微好点那就是在获取的地方加上缓存,貌似不错,但是有个问题是在并发的时候会存在N个请求去获取token,这边需要控制下。

定时的就不存在上面的问题了,但是一定要确保定时任务的正常。

我这边一个token的失效时间为24小时,所以我这边刷新的间隔是20小时,也就是说在token还没过期之前,我会自动刷新成最新的,这样就不会出现token过期的问题了。

while循环是为了确保token能够正确的刷新成功。

同时这个任务是在项目启动之后立马去刷新token的,这样就能确保刚过来的请求不会受到影响。

具体代码可以参考我的github:

https://github.com/yinjihuan/spring-cloud

推荐阅读:

《知识点-Spring Boot 统一异常处理汇总》

《Spring Boot 1.X和2.X优雅重启实战》

《Spring Boot中快速操作Mongodb》

《面试-线程池的成长之路》

原文发布于微信公众号 - 猿天地(cxytiandi)

原文发表时间:2018-05-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏竹清助手

浅谈Linux磁盘修复e2fsck命令

检查 /dev/mapper/VolGroup00-LogVol02 是否有问题,如发现问题便自动修复:

2692
来自专栏美团技术团队

Spring MVC注解故障追踪记

Spring MVC是美团点评很多团队使用的Web框架。在基于Spring MVC的项目里,注解的使用几乎遍布在项目中的各个模块,有Java提供的注解,如:@O...

4207
来自专栏xingoo, 一个梦想做发明家的程序员

如何在Java应用中提交Spark任务?

最近看到有几个Github友关注了Streaming的监控工程——Teddy,所以思来想去还是优化下代码,不能让别人看笑话啊。于是就想改一下之前觉得最丑陋的一...

6896
来自专栏XAI

SpringMVC+MongoDB+Maven整合(微信回调Oauth授权)

个人小程序。里面是基于百度大脑 腾讯优图做的人脸检测。是关于人工智能的哦。 2017年第一篇自己在工作中的总结文档。土豪可以打赏哦。 https://git.o...

8557
来自专栏JAVA高级架构

2017 年你不能错过的 Java 类库

各位读者好, 这篇文章是在我看过 Andres Almiray 的一篇介绍文后,整理出来的。 因为内容非常好,我便将它整理成参考列表分享给大家, 同时附上各个库...

2888
来自专栏ImportSource

刨根问底synchronized | 锁系列-Java中的锁

铺垫 在Java SE 1.5之前,多线程并发中,synchronized一直都是一个元老级关键字,而且给人的一贯印象就是一个比较重的锁。 为此,在Java ...

4665
来自专栏jeremy的技术点滴

docker源码分析-Client创建与命令执行

5172
来自专栏JAVA高级架构

spring和springMVC的面试问题总结

1.Spring中AOP的应用场景、Aop原理、好处? 答:AOP--Aspect Oriented Programming面向切面编程;用来封装横切关注点,具...

3699
来自专栏Petrichor的专栏

git:深挖 .git文件夹

2502
来自专栏代码拾遗

Spring Boot 2.0 教程 - 配置详解

Spring Boot 可以通过properties文件,YAML文件,环境变量和命令行参数进行配置。属性值可以通过,@Value注解,Environment...

1153

扫码关注云+社区

领取腾讯云代金券