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