提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
因为最近在重构之前的聊天室项目,并且打算把认证授权模块集成到网关服务中。所以遇到了网关调用微服务的一系列问题。
一、问题描述
我是打算在网关全局过滤器上面去对token进行验证,然后需要调用认证授权服务。我是使用普通的微服务调用方式:定义openFeign的服务,然后在过滤器上面自动装配该bean去调用token解析服务。但是这个时候会发现微服务调用一直失败,例如返回值一直为null、或者报503服务不存在等。
二、问题剖析
我去debug了一下,发现该自动装配的openFeign的服务bean一直为null。但是如果在Controller中使用该bean倒是正常。那么可以推测在过滤器中的bean可能还没有被加载。所以我查了一下spring的加载顺序为:listener->filter->servlet。由此可知filter的加载在IOC容器之前,所以globalFilter中无法使用注入的bean。这种情况其实会很常见,例如在过滤器中使用某些组件如redis的时候也会发现redisTemplate没有初始化。
三、解决方法
以下是我解决该问题的思路
(1)将过滤器托管给spring
(2)提前加载bean
(3)使用WebClient来调用微服务
解决方案
第一个方案我没试过,网上的资料似乎也比较少
我一般用第二个方案来解决中间件的template的初始化问题
而对于微服务调用的问题我是使用第三种方案。
代码示例
第三中方案的实现代码:
WebClient webClient = WebClient.builder().build();
Mono<String> result = webClient.get().uri("http://localhost:6532/auth-service/checkToken?token="+token).retrieve().bodyToMono(String.class);
String resultJson = result.block();
总结
本来想贴当时的错误代码和报错界面的,但是那个是两星期前的代码版本了,懒得回退了。而且网关做token校验的话,个人感觉最佳实践还是将校验(jwt的校验)逻辑放在网关上面比较好。因为这样子当你的授权服务挂了,网关还是能够对已经登陆的用户提供服务。