路由谓词工厂

Spring Cloud Gateway 将路由匹配作为 Spring WebFlux HandlerMapping 基础设施的一部分。Spring Cloud Gateway 包含许多内置的路由断言工厂。所有这些断言都匹配 HTTP 请求的不同属性。您可以将多个路由断言工厂与逻辑 and 语句结合使用。

After 路由断言工厂

After 路由断言工厂接受一个参数:一个 datetime(即 Java ZonedDateTime)。此断言匹配在指定日期时间之后发生的请求。以下示例配置了一个 After 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]

此路由匹配在 2017 年 1 月 20 日 17:42 山区时间(丹佛)之后发出的任何请求。

Before 路由断言工厂

Before 路由断言工厂接受一个参数:一个 datetime(即 Java ZonedDateTime)。此断言匹配在指定 datetime 之前发生的请求。以下示例配置了一个 Before 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: before_route
        uri: https://example.org
        predicates:
        - Before=2017-01-20T17:42:47.789-07:00[America/Denver]

此路由匹配在 2017 年 1 月 20 日 17:42 山区时间(丹佛)之前发出的任何请求。

Between 路由断言工厂

Between 路由断言工厂接受两个参数:datetime1datetime2,它们是 Java ZonedDateTime 对象。此断言匹配在 datetime1 之后且在 datetime2 之前发生的请求。datetime2 参数必须在 datetime1 之后。以下示例配置了一个 Between 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: between_route
        uri: https://example.org
        predicates:
        - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

此路由匹配在 2017 年 1 月 20 日 17:42 山区时间(丹佛)之后和 2017 年 1 月 21 日 17:42 山区时间(丹佛)之前发出的任何请求。这对于维护窗口可能很有用。

Cookie 路由断言工厂接受两个参数:cookie name 和一个 regexp(即 Java 正则表达式)。此断言匹配具有给定名称且其值与正则表达式匹配的 cookie。以下示例配置了一个 Cookie 路由断言工厂

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p

此路由匹配具有名为 chocolate 的 cookie 且其值与 ch.p 正则表达式匹配的请求。

Header 路由断言工厂

Header 路由断言工厂接受两个参数:header 和一个 regexp(即 Java 正则表达式)。此断言匹配具有给定名称且其值与正则表达式匹配的请求头。以下示例配置了一个 Header 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+

如果请求具有名为 X-Request-Id 的请求头,且其值与 \d+ 正则表达式匹配(即,其值为一个或多个数字),则此路由匹配。

Host 路由断言工厂

Host 路由断言工厂接受一个参数:主机名 patterns 列表。模式是一个 Ant 风格的模式,以 . 作为分隔符。此断言匹配与模式匹配的 Host 请求头。以下示例配置了一个 Host 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org

也支持 URI 模板变量(例如 {sub}.myhost.org)。

如果请求具有 Host 请求头,且其值为 www.somehost.orgbeta.somehost.orgwww.anotherhost.org,则此路由匹配。

此断言将 URI 模板变量(例如前面示例中定义的 sub)提取为名称和值的映射,并将其放在 ServerWebExchange.getAttributes() 中,键由 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 定义。这些值随后可用于 GatewayFilter 工厂

Method 路由断言工厂

Method 路由断言工厂接受一个 methods 参数,该参数是一个或多个 HTTP 方法参数,用于匹配。以下示例配置了一个 Method 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST

如果请求方法为 GETPOST,则此路由匹配。

Path 路由断言工厂

Path 路由断言工厂接受两个参数:一个 Spring PathMatcher patterns 列表和一个可选的 matchTrailingSlash 标志(默认为 true)。以下示例配置了一个 Path 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment},/blue/{segment}

如果请求路径为例如:/red/1/red/1//red/blue/blue/green,则此路由匹配。

如果将 matchTrailingSlash 设置为 false,则请求路径 /red/1/ 将不匹配。

如果您设置了 spring.webflux.base-path 属性,这将影响路径匹配。属性值将自动添加到路径模式的前面。例如,如果 spring.webflux.base-path=/app 且路径模式为 /red/{segment},则用于匹配的完整模式将是 /app/red/{segment}

此断言将 URI 模板变量(例如前面示例中定义的 segment)提取为名称和值的映射,并将其放在 ServerWebExchange.getAttributes() 中,键由 ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE 定义。这些值随后可用于 GatewayFilter 工厂

提供了一个实用方法(称为 get)以方便访问这些变量。以下示例展示了如何使用 get 方法

Map<String, String> uriVariables = ServerWebExchangeUtils.getUriTemplateVariables(exchange);

String segment = uriVariables.get("segment");

Query 路由断言工厂

Query 路由断言工厂接受两个参数:一个必需的 param 和一个可选的 regexp(即 Java 正则表达式)。以下示例配置了一个 Query 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=green

如果请求包含 green 查询参数,则前面的路由匹配。

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=red, gree.

如果请求包含 red 查询参数,且其值匹配 gree. 正则表达式,则前面的路由匹配,因此 greengreet 将匹配。

RemoteAddr 路由断言工厂

RemoteAddr 路由断言工厂接受一个 sources 列表(最小长度为 1),这些源是 CIDR 表示法(IPv4 或 IPv6)字符串,例如 192.168.0.1/16(其中 192.168.0.1 是 IP 地址,16 是子网掩码)。以下示例配置了一个 RemoteAddr 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24

如果请求的远程地址为例如 192.168.1.10,则此路由匹配。

修改远程地址的解析方式

默认情况下,RemoteAddr 路由断言工厂使用来自传入请求的远程地址。如果 Spring Cloud Gateway 位于代理层之后,这可能与实际客户端 IP 地址不匹配。

您可以通过设置自定义的 RemoteAddressResolver 来定制远程地址的解析方式。Spring Cloud Gateway 附带一个非默认的远程地址解析器,该解析器基于 X-Forwarded-For 请求头,即 XForwardedRemoteAddressResolver

XForwardedRemoteAddressResolver 有两个静态构造方法,它们采用不同的安全方法

  • XForwardedRemoteAddressResolver::trustAll 返回一个 RemoteAddressResolver,它始终获取 X-Forwarded-For 请求头中找到的第一个 IP 地址。这种方法容易受到欺骗,因为恶意客户端可以为 X-Forwarded-For 设置初始值,该值将被解析器接受。

  • XForwardedRemoteAddressResolver::maxTrustedIndex 接受一个索引,该索引与 Spring Cloud Gateway 前面运行的受信任基础设施的数量相关。例如,如果 Spring Cloud Gateway 只能通过 HAProxy 访问,则应使用值 1。如果在 Spring Cloud Gateway 可访问之前需要两次受信任基础设施的跳跃,则应使用值 2。

考虑以下请求头值

X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

以下 maxTrustedIndex 值产生以下远程地址

maxTrustedIndex 结果

[Integer.MIN_VALUE,0]

(无效,初始化时发生 IllegalArgumentException

1

0.0.0.3

2

0.0.0.2

3

0.0.0.1

[4, Integer.MAX_VALUE]

0.0.0.1

以下示例展示了如何使用 Java 实现相同的配置

GatewayConfig.java
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
    .maxTrustedIndex(1);

...

.route("direct-route",
    r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")
        .uri("https://downstream1")
.route("proxied-route",
    r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")
        .uri("https://downstream2")
)

Weight 路由断言工厂

Weight 路由断言工厂接受两个参数:groupweight(一个整数)。权重按组计算。以下示例配置了一个 Weight 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: weight_high
        uri: https://weighthigh.org
        predicates:
        - Weight=group1, 8
      - id: weight_low
        uri: https://weightlow.org
        predicates:
        - Weight=group1, 2

此路由将把约 80% 的流量转发到 weighthigh.org,将约 20% 的流量转发到 weightlow.org

XForwarded Remote Addr 路由断言工厂

XForwarded Remote Addr 路由断言工厂接受一个 sources 列表(最小长度为 1),这些源是 CIDR 表示法(IPv4 或 IPv6)字符串,例如 192.168.0.1/16(其中 192.168.0.1 是 IP 地址,16 是子网掩码)。

此路由断言允许根据 X-Forwarded-For HTTP 请求头过滤请求。

这可以与负载均衡器或 Web 应用程序防火墙等反向代理一起使用,其中只有当请求来自这些反向代理使用的受信任 IP 地址列表时才允许请求。

以下示例配置了一个 XForwardedRemoteAddr 路由断言

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: xforwarded_remoteaddr_route
        uri: https://example.org
        predicates:
        - XForwardedRemoteAddr=192.168.1.1/24

如果 X-Forwarded-For 请求头包含例如 192.168.1.10,则此路由匹配。

© . This site is unofficial and not affiliated with VMware.