Spring Gateway全局过滤器

Posted 流楚丶格念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Gateway全局过滤器相关的知识,希望对你有一定的参考价值。

文章目录

全局过滤器

刚刚学习的过滤器,网关提供了31种,但每一种过滤器的作用都是固定的。如果我们希望拦截请求,做自己的业务逻辑则没办法实现。

这就引出了我们的Spring Gateway全局过滤器。他可以实现过滤请求的时候按照自己的自己的业务逻辑进行路由的处理。

1. 全局过滤器作用

全局过滤器的作用也是处理一切进入网关的请求和微服务响应,与GatewayFilter的作用一样。

区别在于GatewayFilter(网关过滤器)通过配置定义,处理逻辑是固定的;而GlobalFilter(全局过滤器)的逻辑需要自己写代码实现。

在filter中编写自定义逻辑,可以实现下列功能:
(后期会单独发博客去整理案例)

  • 登录状态判断
  • 权限校验
  • 请求限流等

2. 自定义全局过滤器

2.1 GlobalFilter接口

自定义全局过滤器 定义方式是实现GlobalFilter接口,GlobalFilter接口声明如下:

public interface GlobalFilter 
    /**
     *  处理当前请求,有必要的话通过@link GatewayFilterChain将请求交给下一个过滤器处理
     *
     * @param exchange 请求上下文,里面可以获取Request、Response等信息
     * @param chain 用来把请求委托给下一个过滤器 
     * @return @code Mono<Void> 返回标示当前过滤器业务结束
     */
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);

我们在时候使用时直接实现接口即可

2.1 Ordered接口

每一个过滤器都必须指定一个int类型的order值,order值越小,过滤器优先级越高,执行顺序越靠前。

GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定

例如:

  • 实现Ordered 接口

    public class AuthorizeFilter implements GlobalFilter, Ordered 
    
    	// 业务逻辑...
    	
        @Override
        public int getOrder() 
            return -1;
        
    
    
  • 或者添加@Order注解

    @Order(-1)
    @Component
    public class AuthorizeFilter implements GlobalFilter 
    	// 业务逻辑...
    
    

那么就有一个问题了,路由过滤器与默认过滤器有order吗?

路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。

2.1 自定义全局过滤器案例

案例需求:定义全局过滤器,拦截请求,判断请求的参数是否满足下面条件:

  • 参数中是否有authorization,
  • authorization参数值是否为admin

如果同时满足则放行,否则拦截

代码实现:

在gateway中定义一个过滤器:

package cn.itcast.gateway.filters;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter 
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) 
        // 1.获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2.获取authorization参数
        String auth = params.getFirst("authorization");
        // 3.校验
        if ("admin".equals(auth)) 
            // 放行
            return chain.filter(exchange);
        
        // 4.拦截
        // 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 4.2.结束处理
        return exchange.getResponse().setComplete();
    

debug测试运行一下

打个断点我们可以看到exchange里存的是请求信息

如果携带了参数,就能查到

不携带被拦截

3.过滤器执行顺序

请求进入网关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter

请求路由后,会将DefaultFilter、当前路由过滤器 和 GlobalFilter,合并到一个过滤器链(集合)中,排序后依次执行每个过滤器:


按照上面的案例应该是:

default-filter > user-service  > global-filter

排序的规则是什么呢?

  • 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前
  • GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
  • 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。
  • 当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

详细内容,可以查看源码:

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()方法会加载全局过滤器,与前面的过滤器合并后根据order排序,组织过滤器链

以上是关于Spring Gateway全局过滤器的主要内容,如果未能解决你的问题,请参考以下文章

spring cloud gateway 某些路由中跳过全局过滤器

Spring Cloud Gateway--全局过滤器(GlobalFilter)--作用/使用

spring cloud gateway 修改responseBody全局过滤器

spring cloud gateway 修改responseBody全局过滤器

spring-cloud-gateway之GatewayFilterFactory

Spring Cloud Gateway—网关