微服务自定义过滤器

一、网关登录校验

单体架构时我们只需要完成一次用户登录、身份校验,就可以在所有业务中获取到用户信息。而微服务拆分后,每个微服务都独立部署,不再共享数据。也就意味着每个微服务都需要做登录校验,这显然不可取。

1.1、鉴权思路分析

我们的登录是基于JWT来实现的,校验JWT的算法复杂,而且需要用到秘钥。如果每个微服务都去做登录校验,这就存在着两大问题:

  • 每个微服务都需要知道JWT的秘钥,不安全

  • 每个微服务重复编写登录校验代码、权限校验代码,麻烦

既然网关是所有微服务的入口,一切请求都需要先经过网关。我们完全可以把登录校验的工作放到网关去做,这样之前说的问题就解决了:

  • 只需要在网关和用户服务保存秘钥

  • 只需要在网关开发登录校验功能

1.2、网关过滤器

登录校验必须在请求转发到微服务之前做,否则就失去了意义。而网关的请求转发是Gateway内部代码实现的,要想在请求转发之前做登录校验,就必须了解Gateway内部工作的基本原理。

如图所示:

  1. 客户端请求进入网关后由HandlerMapping对请求做判断,找到与当前请求匹配的路由规则(Route ),然后将请求交给WebHandler去处理。
  2. WebHandler则会加载当前路由下需要执行的过滤器链(Filter chain ),然后按照顺序逐一执行过滤器(后面称为**Filter**)。
  3. 图中Filter被虚线分为左右两部分,是因为Filter内部的逻辑分为prepost两部分,分别会在请求路由到微服务之前之后被执行。
  4. 只有所有Filterpre逻辑都依次顺序执行通过后,请求才会被路由到微服务。
  5. 微服务返回结果后,再倒序执行Filterpost逻辑。
  6. 最终把响应结果返回。

最终请求转发是有一个名为NettyRoutingFilter的过滤器来执行的,而且这个过滤器是整个过滤器链中顺序最靠后的一个。如果我们能够定义一个过滤器,在其中实现登录校验逻辑,并且将过滤器执行顺序定义到 NettyRoutingFilter 之前,这就符合我们的需求了!

网关过滤器链中的过滤器有两种:

  • GatewayFilter :路由过滤器,作用范围比较灵活,可以是任意指定的路由Route.

  • GlobalFilter:全局过滤器,作用范围是所有路由,不可配置。

其实GatewayFilterGlobalFilter这两种过滤器的方法签名完全一致:

复制代码
/**
 * 处理请求并将其传递给下一个过滤器
 * @param exchange 当前请求的上下文,其中包含request、response等各种数据
 * @param chain 过滤器链,基于它向下传递请求
 * @return 根据返回值标记当前请求是否被完成或拦截,chain.filter(exchange)就放行了。
 */
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);

FilteringWebHandler在处理请求时,会将GlobalFilter装饰为GatewayFilter,然后放到同一个过滤器链中,排序以后依次执行。

Gateway内置的GatewayFilter过滤器使用起来非常简单,无需编码,只要在yaml文件中简单配置即可。而且其作用范围也很灵活,配置在哪个Route下,就作用于哪个Route.

1.2.1、自定义过滤器(GlobalFilter)

以**Gateway为例做一次演示**

由于GlobalFilter是一个接口创建一个 MyGlobalFilter 类加**@compoent** 注解注册成spring Bean上并实现GlobalFilter, 并实现filter方法

1.首先在exchange 获取getRequest

  1. getRequest中获取请求头

3.使用chain.filter()放行。

过滤器定义就完成了,接下来需要确保我的的过滤器在NettyRoutrngFilter之前执行。

在ider中按下Ctrl+H点击NettyRoutingFilter

我们发现NettyRoutingFilter不仅继承了GlobalFilter还有Ordered。

而Ordered会要求你实现getOrder()方法。返回的返回值数值越小就越快执行,而getOrder()方法的返回值是2147483647也就是最低优先级。

明白了以上原理后我们就明白这么在NettyRoutingFilter之前执行过滤器。首先实现Ordered,并实现getOrder()方法返回值设置为0比2147483647小那么就理所当然优先执行了

接下来我们设置断点测试就会发现得到了所有的请求头

1.2.1、自定义过滤器(GatewayFilter

自定义GatewayFilter不是直接实现GatewayFilter,而是实现AbstractGatewayFilterFactory

示例:

创建一个PrintAnyGatewayFilterFactory 类并继承AbstractGatewayFilterFactory 继承AbstractGatewayFilterFactory 需要一个泛型我们填写Object即可

在 apply方法中构造你需要的过滤器,由于GatewayFilter是一个接口所以我们就匿名实现。

但是新的问题又来了,我们之前编写了一个全局过滤器,创建的又是匿名内部类,无法继续实现,无法实现Ordered就无法确定顺序。所以提供了一个装饰类OrderedGatewayFilter他同时实现了GlobalFilter和Ordered

需要带顺序的过滤器可以使用 OrderedGatewayFilter装饰类

以上是无参的**GatewayFilter而,有参和无参的不同点在于**

  1. Config:方法自定义配置属性,成员变量名称非常重要
  2. PrintAnyGatewayFilterFactory:将Config字节码传递给父类,父类负责帮我们读取yaml配置
  3. shortcutFieldOrder:将变量按照一定的顺序进行返回

相关推荐
ClouGence7 小时前
Oracle CDC 架构优化:从主库直连到 DataGuard 备库同步
数据库·后端·oracle
无响应de神9 小时前
三、用户与权限管理
数据库·mysql
大树881 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠1 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质1 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
Inhand陈工1 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智1 天前
ARP代理--工作原理
运维·网络·arp·arp代理
麦聪聊数据1 天前
数据服务化时代:企业数据能力输出的核心路径
数据库
shushangyun_1 天前
2026年快消品B2B系统推荐:支持终端门店订货、促销政策自动化的工具?
java·运维·网络·数据库·人工智能·spring·自动化
DARLING Zero two♡1 天前
【MySQL数据库】数据类型与表约束
数据库·mysql