过滤器

2022-09-15 14:20:58 浏览数 (1)

1、认识过滤器

1.1、过滤器的基本知识

微服务系统中的服务非常多。如果每个服务都自己做鉴权、限流、日志输出,则非常不科学。所以可以通过网关的过滤器来处理这些工作。在用户访问各个服务前,应在网关层统一做好鉴权、限流等工作。

1.2、Filter生命周期

根据生命周期可以将Spring Cloud Gateway中的Filter分为"PRE"和"POST"两种:

**PRE:**代表在请求被路由之前执行该过滤器。此种过滤器可用来实现参数校验、权限校验、流量监控、日志输出、协议转换等工能

**POST:**代表在请求被路由到微服务之后执行该过滤器。此种过滤器可用来实现响应头的修改(如添加标准的HTTP Header)、收集统计信息和指标、将响应发送给客户端、输出日志、流量监控等功能

1.3、Filter分类

根据作用范围,Filter可以分为以下两种:

**GatewayFilter:**网关过滤器。此种过滤器只应用在单个路由或者一个分组的路由上

**GlobalFilter:**全局过滤器。此种过滤器会应用在所有的路由上

2、网关过滤器

网关过滤器允许以某种方式修改传入的HTTP请求,或输出的HTTP响应。网关过滤器作用于特定路由。Spring Cloud Gateway内置了许多过滤器工厂来编写网关过滤器。

2.1、AddRequestHeader网关过滤器工厂

它用于在请求头中添加自定义的键值对。

2.2、AddRequestParameter网关过滤器工厂

它用于在请求中添加请求参数的键值对。

2.3、AddResponseHeader网关过滤器工厂

它用于在响应头中添加键值对。

2.4、Hystrix网关过滤器工厂

它用于将断路器引入网关路由中,让服务免受级联故障的影响,并在故障时提供回退响应。在使用时需要一个名为"HystrixCommand"的参数。

2.5、Prefix网关过滤器工厂

它用于使简单的Prefix参数。

2.6、PreserveHostHeader网关过滤器工厂

它用于设置路由过滤器的请求属性,检查是否发送原始主机头或由HTTP客户端确定主机头。

2.7、RequestRateLimiter网关过滤器工厂

它用于确定当前请求是否允许继续。如果不允许,则返回提示"HTTP 429 -Too Many Requests"。

2.8、RedirectTo网关过滤器工厂

它用于接收请求的状态和URL的参数。该状态是一个重定向的300系列的HTTP代码,如301。URL是Location头部的值。

2.9、RemoveNonProxyHeaders网关过滤器工厂

它用于从转发的请求中删除请求头。

2.10、RemoveRequestHeader网关过滤器工厂

它用于删除请求头,它需要请求头名。

2.11、RemoveResponseHeader网关过滤器工厂

它用于删除响应头,它需要响应头名。

2.12、RewritePath网关过滤器工厂

它用于使用Java正则表达式重写请求路径。

2.13、SaveSession网关过滤器工厂

它用于在转发到下游之前强制执行保存Session操作。

2.14、SecureHeaders网关过滤器工厂

它用于为响应添加安全头。

2.15、SetPath网关过滤器工厂

它提供了一种方法,该方法允许通过路径的模板来操作请求路径。它使用了Spring框架的URI模板,支技多种匹配。

2.16、SetResponseHeader网关过滤器工厂

它用于设置响应头,需要有一个Key-Value对。

2.17、SetStatus网关过滤器工厂

它用于设置请求响应状态,它需要一个Status参数,该参数的值必须是有效的Spring HttpStatus。例如,整型的404或枚举类型的字符串NOT_FOUND。

2.18、StripPrefix网关过滤工厂

它用于剥离前缀。它需要parts参数,表明在请求被发送到下游之前从请求路径中剥离的元素数量。

2.19、Retry网关过滤工厂

它用于进行重试,它需要Retries、Statuses、Methods和Series参数

**Retries:**重试次数

**Statuses:**重试的HTTP状态代码,用org.springframework.http.HttpStatus表示

**Methods:**重试的HTTP方法,用org.springframework.http.HttpMethod表示

**Series:**重试的状态代码,用org.springframework.http.HttpStatus.Series表示

2.20、RequestSize网关过滤器工厂

它用于限制请求的大小。当请求超过限制时启用,限制请求到达下游服务。该过滤器将RequestSize作为参数。

3、全局过滤器

全局过滤器由一系列特殊的过滤器组成。它会应用到所有路由中。

3.1、Forward路由过滤器(Forward Routing Filter)

它在exchange的属性中查找URI。如果URI是forward协议,则它将用Spring DispatcherHandler处理请求。

3.2、LoadBalancerClient路由过滤器(LoadBalancerClient Filter)

它在exchange的属性中查找URI。如果URI是lb协议,则它用Spring Cloud LoadBalancerClient将名称(lb://myservice中的myservice)解析为实际的主机和端口,并替换URI中的相同属性。

3.3、Netty路由过滤器(Netty Routing Filter)

如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR中的URI使用的是HTTP或HTTPS协议,则运行Netty路由过滤器。它用Netty HttpClient发出下游代理请求。

3.4、Netty写响应过滤器(Netty Write Response Filter)

如果在ServerWebUtils.CLIENT_RESPONSE_ATTR的值存在Netty HttpClientResponse,则运行Netty写响应过滤器。它在所有其他过滤器完成后运行,并将代理响应写回到网关客户端的响应数据中。

3.5、RouteToRequestUrl过滤器(RouteToRequestUrl Filter)

如果在ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR的值中存在Route对象,则运行路由到请求地址。

3.6、Websocket路由过滤器(Websocket Routing Filter)

如果ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR值的URI是ws协议或wss协议,则运行Websocket路由过滤器。它利用Spring Web Socket底层代码将Web Socket请求转发到下游。

3.7、网关指标过滤器(Gateway Metrics Filter)

要启用它需要添加spring-boot-starter-actuator的依赖。默认情况下,只要属性spring.cloud.gateway.metrics.enabled未设置为false,网关指标过滤器就会运行。此过滤器会添加一个名为"gateway.requests"的指标(Metrics),其中包含以下属性:

routeId:路由ld

routeUri:API将被路由到的URI

outcome:由HttpStatus.Series分类的结果

status:HTTP请求返回给客户端的状态

3.8、组合式全局过滤器和网关过滤器排序(Combined Global Filter and GatewayFilter Ordering)

当请求进入并匹配到一个路由时,Filtering Web Handler会将GlobalFilter的所有实例和GatewayFilter的所有路由特定实例添加到过滤器链中。这个组合的过滤器链由org.springframework.core.Ordered接口排序。

3.9、路由交换(Marking An Exchange As Routed)

网关在路由了ServerWebExchange后,会通过将gatewayAlreadyRouted添加到exchange属性来将该交换标识为"路由"。一旦请求被标识为路由,则其他路由过滤器会跳过该请求。

4、使用Global过滤器实现用户认证

4.1、添加网关依赖

代码语言:javascript复制
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

4.2、添加配置

代码语言:javascript复制
#id:自定义路由ID
spring.cloud.gateway.routes[0].id=addrequestheader_route1
#uri:目标服务地址
spring.cloud.gateway.routes[0].uri=http://localhost:50006
#predicates:路由条件。Predicate根据输入参数返回一个布尔值。其包含多种默认方法来将Predicate组合成复杂的路由逻辑
spring.cloud.gateway.routes[0].predicates[0]=Path=/hello

4.3、添加TokenFilter

代码语言:javascript复制
public class TokenFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //从请求中token参数
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        //如果为null或空直接返回401未认证错误
        if (StringUtils.isEmpty(token)){
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        //如果包含则放行
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -100;
    }
}

4.4、添加Gateway配置类

代码语言:javascript复制
@Configuration
public class GatewayConfig {

    @Bean
    public TokenFilter tokenFilter(){
        return new TokenFilter();
    }
}

4.5、测试

访问:http://localhost:50024/hello

0 人点赞