【RuoYi-Cloud项目研究】【ruoyi-gateway模块】介绍RuoYi网关的过滤器
本文主要介绍 RuoYi 中用到的过滤器,以及过滤器原理简单分析。Spring Gateway 的详细原理请参考作者另外的文章。
本文主要介绍 RuoYi 中用到的过滤器,以及过滤器原理简单分析。Spring Gateway 的详细原理请参考作者另外的文章。
1. 网关的过滤器清单
在“网关模块”一共定义了5个过滤器。分类如下:
-
继承AbstractGatewayFilterFactory的
-
- ValidateCodeFilter(验证码过滤器)
- BlackListUrlFilter(黑名单过滤器)
- CacheRequestFilter
-
实现GlobalFilter, Ordered接口
-
- XssFilter(跨站脚本过滤器)
- AuthFilter(网关鉴权)
2. GatewayFilterFactory和GlobalFilter 的原理
有以下几个问题需要解决
- 继承 AbstractGatewayFilterFactory 类和实现 GlobalFilter, Ordered 接口 2 种方式的过滤器有什么不同?
GlobalFilter 参考:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-combined-global-filter-and-gatewayfilter-ordering
GatewayFilterFactory参考:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
关键是:GlobalFilter 针对“所有路由”,而 GatewayFilterFactory 针对“特定路由”
- 为什么实现 Spring 的 Ordered 接口
为了控制过滤器的顺序,Spring 的 Ordered 接口是根据 order 值升序排序的。
- 既有继承又有实现接口,它们的顺序是怎么样的
public Mono<Void> handle(ServerWebExchange exchange) {
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
List<GatewayFilter> gatewayFilters = route.getFilters();
List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
combined.addAll(gatewayFilters);
// TODO: needed or cached?
AnnotationAwareOrderComparator.sort(combined);
if (logger.isDebugEnabled()) {
logger.debug("Sorted gatewayFilterFactories: " + combined);
}
return new DefaultGatewayFilterChain(combined).filter(exchange);
}
从以上 combine 可以看到先从请求 request 属性中获取了特定路由的过滤器gatewayFilters,在结合全局过滤器combined,最后经过 Ordered 排序。但是继承GatewayFilterFactory并没有指定 order 的值,只有实现 Ordered 接口才指定了 order 值,此时怎么处理GatewayFilterFactory的???
猜测:是不是跟 nacos 的网关 route 配置的 filters 的顺序有关呢。
结论:猜测正确✅
3. RuoYi网关的配置文件是如何配置的
- 各个服务的路由配置是怎么样的(特别是 auth 认证服务)
在 nacos 的网关配置文件 ruoyi-gateway-dev.yml 中给 ruoyi-auth 模块多配置了几个过滤器 filter。
spring:
redis:
host: localhost
port: 6379
password:
cloud:
gateway:
discovery:
locator:
lowerCaseServiceId: true
enabled: true
routes:
# 认证中心
- id: ruoyi-auth
uri: lb://ruoyi-auth
predicates:
- Path=/auth/**
filters:
# 验证码处理
- CacheRequestFilter
- ValidateCodeFilter
- StripPrefix=1
# 代码生成
- id: ruoyi-gen
uri: lb://ruoyi-gen
predicates:
- Path=/code/**
filters:
- StripPrefix=1
# 定时任务
- id: ruoyi-job
uri: lb://ruoyi-job
predicates:
- Path=/schedule/**
filters:
- StripPrefix=1
# 系统模块
- id: ruoyi-system
uri: lb://ruoyi-system
predicates:
- Path=/system/**
filters:
- StripPrefix=1
# 文件服务
- id: ruoyi-file
uri: lb://ruoyi-file
predicates:
- Path=/file/**
filters:
- StripPrefix=1
# 安全配置
security:
# 验证码
captcha:
enabled: true
type: math
# 防止XSS攻击
xss:
enabled: true
excludeUrls:
- /system/notice
# 不校验白名单
ignore:
whites:
- /auth/logout
- /auth/login
- /auth/register
- /*/v2/api-docs
- /csrf
其中给Auth模块特别配置了CacheRequestFilter、ValidateCodeFilter。其它模块全局使用了XssFilter、AuthFilter过滤器
- 如果有多个过滤器,那么执行顺序是怎么样的。
全局的过滤器globalFilters是可以定义order值的,不能定义orderd值的局部过滤器(跟特定路由绑定)是依据 yml 配置文件配置的顺序(先配置的orderd值是1,递增的)。所以 yml 配置中只配置跟路由相关的局部过滤器。
- auth 服务的有哪些过滤器
结合gatewayFilters是按照配置文件的顺序(order是1,2,3依次递增),globalFilters也是按照order的顺序排序。所以对于RuoYi的过滤器来说顺序是:
AuthFilter(order=-200)
XssFilter(order=-100)
CacheRequestFilter(order=1)
ValidateCodeFilter(order=2)
StripPrefix(order=3)
4. 资料参考
语雀笔记地址:https://www.yuque.com/yuchangyuan/tkb5br
4.1. 过滤器顺序的原理
1、先找到断言处理器的映射规则类RoutePredicateHandlerMapping
2、该类的getHandlerInternal方法中的lookupRoute方法会决定采用哪一个route,并设置到request属性中
3、然后是FilteringWebHandler的handler方法
4、handler方法中获取到route的gatewayFilters和全局的globalFilters,然后按照order升序排序。
猜测route的gatewayFilters的order属性1,2,3是不是按照配置中心配置排序的。改变下配置中心的配置重新debug观察下。(猜测正确)
更多推荐
所有评论(0)