• Spring Cloud Gateway 断言(Predicate) (hoxton 版本)


    https://docs.spring.io/spring-cloud-gateway/docs

    Spring Cloud Gateway将路由匹配作为Spring WebFlux HandlerMapping基础架构的一部分。 Spring Cloud Gateway包括许多内置的Route Predicate工厂。 所有这些Predicate都与HTTP请求的不同属性匹配。 多个Route Predicate工厂可以进行组合。

      Spring Cloud Gateway内置了许多Predict,这些Predict的源码在org.springframework.cloud.gateway.handler.predicate包中,如果读者有兴趣可以阅读一下。现在列举各种Predicate如下图:

    After Route Predicate Factory

           这个Predicate工厂的实现类是AfterRoutePredicateFactory,使用一个时间参数,如果当前请求的时间在配置的赶时间之后,此断言才会返回true。在application.yml中如下配置所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: after_route
            uri: http://www.xinyues.com  # 如果断言返回true,路由到的URI
            predicates:
            - After=2017-01-20T17:42:47.789-07:00[America/Denver]

    注意这个类使用的时间类是ZonedDateTime,表示ISO-8601日历系统中具有时区的日期时间,所以在application.yml中的时间配置格式只能是:2017-01-20T17:42:47.789-07:00[America/Denver],字符串的时间格式转化为ZonedDateTime使用的是StringToZonedDateTimeConverter类。如果想使用其它的时间格式,得需要自己实现一个单独的转化类了。通过源码中的测试例子可以看到,如果请求在配置的时间之前,网关会返回404,如果在配置的时间之后,网关路由成功到http://www.xinyues.com 网站。

          这里简单说一下spring.cloud.gateway.routes的配置,它对应的是一个List列表,List列表存储的对象类型是RouteDefinition,这是一个路由的定义类。id是在这个List列表中所有的路由定义中必须唯一,可以随便定义。在RouteDefinition声明的字段,在application.yml中的spring.cloud.gateway.routes中都可以配置。

    Before Route Predicate Factory

           这个Predicate工厂的实现类是BeforeRoutePredicateFactory,它和AfterRoutePredicateFactory的实现基本上是一致的,在application.yml中的配置如下所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: before_route
            uri: http://www.xinyues.com # 路由到的URI
            predicates:
            - Before=2017-01-20T17:42:47.789-07:00[America/Denver]

    如果当前请求的时间在配置的时间之前,此断言返回true,网关将请求路由到http://www.xinyues.com网站。否则,返回404。

    Between Route Predicate Factory

           这个Predicate的工厂实现类是BetweenRoutePredicateFactory,它有两个参数,datatime1,datetime2,在application.yml中的配置如下:

    spring:
      cloud:
        gateway:
          routes:
          - id: between_route
            uri: http://www.xinyues.com
            predicates:
            - Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]

    当请求网关的时间在datatime1之后,在datetim2之前时,这个断言返回true,会将请求路由到http://www.xinyues.com网站。这个断言对于维护一个时间窗口很有用。比如限制在基某段时间内开启的活动,非这个时间段不可以访问等。

    Cookie Route Predicate Factory

           这个Predicate工厂的实现类是CookieRoutePredicateFactory,它有两个参数,一个是name,另一个是正则表达式。在application.,yml中的配置如下所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: cookie_route
            uri: http://www.xinyues.com
            predicates:
            - Cookie=username, wgslcuky

    如果请求的Cookie中有name的值,并且根据name取出的值都匹配配置的正则表达式,这个断方就返回true,会将请求路由到http://www.xinyues.com网站。上面的配置就是表示Cookie中username的值是wgslucky时,断言返回true.

    Header Route Predicate Factory

           这个Predicate工厂的实现类是HeaderRoutePredicateFactory,它有两个参数,一个是name,另一个是正则表达式。在application.yml中的配置如下所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: header_route
            uri: http://www.xinyues.com
            predicates:
            - Header=X-Request-Id, \d+

    如果请求的Header里面有name的值,并且它的值与配置的正则表达式匹配,则断言返回true,如果没有配置正则表达式的值,断言也是返回true(断方只检测带正则表达式的配置),将会把请求路由到http://www.xinyues.com网站。上面的配置示例表示Header中必须有X-Request-Id,且它的值必须是数字。

    Host Route Predicate Factory

           这个Predicate的工厂的实现类是HostRoutePredicateFactory,这有一个参数,这个参数是一人List列表,它可以包含多个主机名字匹配的样式。它遵循Ant的样式风格,以点(.)分隔。在application.yml中的配置如下所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: host_route
            uri: http://www.xinyues.com
            predicates:
            - Host=**.somehost.org,**.anotherhost.org,{sub}.myhost.org

    上面示例中Host对应的URI模板变量同样也支持{sub}.myhost.org格式的配置。如果请求的Header中的Host的值是www.sonmehost.org,abc.somehost.org,api.anotherhost.org,这个断言就会返回true,将请求路由到http://www.xinyues.com网站

    在断方工厂中会提取上面配置中Host对应的URI模板变量(比如上面的sub),把匹配的URI放到一个Map中,这个Map会被添加到ServerWebExchange.getAttributes(ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE)的属性集中。可以在后面的Gateway Filter工厂类使用。

    注意,在配置Host的时候,如果Host不是80端口,在配置的时候也需要添加上端口。如:localhost:8080

    Method Route Predicate Factory

           这个Predicate的实现类是MethodRoutePredicateFactory,它有一个参数:指定的Http方法名。在application.yml中的配置如下所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: method_route
            uri: http://www.xinyues.com
            predicates:
            - Method=GET

    如果这个请求的方法名是GET,断言将返回true,将请求路由到http://www.xinyues.com网站

    Path Route Predicate Factory

           这个Predicate的实现类是PathRoutePredicateFactory,它有两个参数,一个是匹配样式列表,另一个是boolean值,表示是否匹配分隔线。在application.yml中的配置好下所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: path_route
            uri: http://www.xinyues.com
            predicates:
            - Path=/foo/{segment},/bar/{segment}

    如果请求的URI中的路径是/foo/1,/foo/bar或/bar/baz,这个断言将返回true,会将请求路由到http://www.xinyues.com网站。这个断言工厂将会提取配置的URI格式中的变量(比如上面配置的segment),并将它转化为Map,替换掉ServerWebExchange.getAttributes(ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE)中的值。这个值可以在GatewayFilter工厂中使用。有一个方法可以方便的访问这些值,如下面代码所示:

    Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
    
    String segment = uriVariables.get("segment");

    Query Route Predicate Factory

        这个是参数路由断言工厂,它的实现类是QueryRoutePredicateFactory,它有两个参数,一个是参数(param),这个是必须的,另一个是可选参数,是一个正则表达式。在application.yml中不带正则的配置如下所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: query_route
            uri: http://www.xinyues.com
            predicates:
            - Query=baz

    如果请求的参数中包含baz参数,断言将返回true,并将请求路由到http://www.xinyues.com网站。带正则表达式的配置如下所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: query_route
            uri: http://example.org
            predicates:
            - Query=foo, ba.

    如果请求的参数中包含foo,且它的值匹配ba.,断言将返回true,并将请求路径到http://www.xinyues.com网着

    RemoteAddr Route Predicate Factory

        这个是远程地址路由断言工厂,它的实现类是RemoteAddrRoutePredicateFactory,它有一个List列表的参数,这些参数是CIDR-notation(IPv4和IPv6)的地址字符串,比如192.168.0.1/16(192.168.0.1是ip地址,16是一个子网掩码)。在application.yml中的配置如下所示:

    spring:
      cloud:
        gateway:
          routes:
          - id: remoteaddr_route
            uri: http://www.xinyues.com
            predicates:
            - RemoteAddr=192.168.1.1/24

    如果请求的客户端的ip地址是192.168.1.1到192.168.1.24的范围,此断言返回true,并将请求路由到http://www.xinyues.com网站。比如192.168.1.10。

    修改远程地址的解析方式

        默认情况下,RemoteAddrRoutePredicateFactory中用到的远程客户端的IP地址是从请求中获取的,但是,如果Spring Cloud Gateway是部署在一个代理服务之后的话,这可能就匹配不到真实的客户端IP地址。这样的话,你可以实现RemoteAddressResolver接口,自定义一个IP地址的解析方式。在Spring Cloud Gateway中有一个非默认的远程IP地址解析器XForwardedRemoteAddressResolver,它是基于X-Forwarded-For header实现的。XForwardedRemoteAddressResolver有两个静态的构造方法,可以用于不同的安全策略:XForwardedRemoteAddressResolver::trustAll方法返回一个RemoteAddressResolver实例,它返回从X-Forwarded-For header获取到的第一个IP地址。这种方式容易受到欺骗攻击,恶意的客户端可以给X-Forwarded-For设置一个初始化的值,这个值对于解析器来说是可以接受的。XForwardedRemoteAddressResolver::maxTrustedIndex需要一个索引值做为参数,这个值和Spring Cloud Gateway前面受信任的代理设备数量相关。比如,如果Spring Cloud Gateway只可以通过HAPoxy访问,那么maxTrustedIndex应该设置为1,如果需要通过两个受信任的设备访问,那么这个值应该设置为2。比如在Header中的X-Forwarded-For值如下所示:

    X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3

    那么maxTrustedIndex的值与下面的远程相对应:

    maxTrustedIndex

    result

    [Integer.MIN_VALUE,0]

    (invalid, IllegalArgumentException during initialization

    1

    0.0.0.3

    2

    0.0.0.2

    3

    0.0.0.1

    [4, Integer.MAX_VALUE]

    0.0.0.1

    如下面代码所示:

    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")
    - Header=X-Request-Id,\d+
    server:
      port: 8060
    spring:
      application:
        name: api-gateway
      cloud:
        # gateway的配置
        gateway:
          # 路由规则
          routes:
            - id: order_route # 路由的唯一标识, 路由到 order
              #          uri: http://localhost:8020 # 需要转发的地址
              uri: lb://order-nacos-service # 需要转发的地址  lb:使用nacos中的本地负载均衡策略
              # 断言规则 用于路由规则的匹配
              predicates:
                - Path=/order-serv/**
                  # http://localhost:8060/order-serv/order/add 路由转到
                # http://localhost:8020/order-serv/order/add
                - After=2017-01-20T17:42:47.789-07:00[Asia/Shanghai]
                - Header=X-Request-Id,\d+
    #            - Mehtod=GET
              filters:
                - StripPrefix=1  # 转发之前去掉第一层路径
                  # http://localhost:8020/order-serv/order/add 过虑成
                # http://localhost:8020/order/add
        # 配置 Nacos
        nacos:
          server-addr: 127.0.0.1:8848
          discovery:
            #        server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            namespace: public

    - Method=GET
    server:
      port: 8060
    spring:
      application:
        name: api-gateway
      cloud:
        # gateway的配置
        gateway:
          # 路由规则
          routes:
            - id: order_route # 路由的唯一标识, 路由到 order
              #          uri: http://localhost:8020 # 需要转发的地址
              uri: lb://order-nacos-service # 需要转发的地址  lb:使用nacos中的本地负载均衡策略
              # 断言规则 用于路由规则的匹配
              predicates:
                - Path=/order-serv/**
                  # http://localhost:8060/order-serv/order/add 路由转到
                # http://localhost:8020/order-serv/order/add
                - After=2017-01-20T17:42:47.789-07:00[Asia/Shanghai]
                - Header=X-Request-Id,\d+
                - Method=GET
              filters:
                - StripPrefix=1  # 转发之前去掉第一层路径
                  # http://localhost:8020/order-serv/order/add 过虑成
                # http://localhost:8020/order/add
        # 配置 Nacos
        nacos:
          server-addr: 127.0.0.1:8848
          discovery:
            #        server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            namespace: public

     

     

    - Query=name
    server:
      port: 8060
    spring:
      application:
        name: api-gateway
      cloud:
        # gateway的配置
        gateway:
          # 路由规则
          routes:
            - id: order_route # 路由的唯一标识, 路由到 order
              #          uri: http://localhost:8020 # 需要转发的地址
              uri: lb://order-nacos-service # 需要转发的地址  lb:使用nacos中的本地负载均衡策略
              # 断言规则 用于路由规则的匹配
              predicates:
                - Path=/order-serv/**
                  # http://localhost:8060/order-serv/order/add 路由转到
                # http://localhost:8020/order-serv/order/add
    #            - After=2017-01-20T17:42:47.789-07:00[Asia/Shanghai]
    #            - Header=X-Request-Id,\d+
    #            - Method=GET
                - Query=name
              filters:
                - StripPrefix=1  # 转发之前去掉第一层路径
                  # http://localhost:8020/order-serv/order/add 过虑成
                # http://localhost:8020/order/add
        # 配置 Nacos
        nacos:
          server-addr: 127.0.0.1:8848
          discovery:
            #        server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            namespace: public

     

     

    - Query=name,zhangsan|lisi
    server:
      port: 8060
    spring:
      application:
        name: api-gateway
      cloud:
        # gateway的配置
        gateway:
          # 路由规则
          routes:
            - id: order_route # 路由的唯一标识, 路由到 order
              #          uri: http://localhost:8020 # 需要转发的地址
              uri: lb://order-nacos-service # 需要转发的地址  lb:使用nacos中的本地负载均衡策略
              # 断言规则 用于路由规则的匹配
              predicates:
                - Path=/order-serv/**
                  # http://localhost:8060/order-serv/order/add 路由转到
                # http://localhost:8020/order-serv/order/add
    #            - After=2017-01-20T17:42:47.789-07:00[Asia/Shanghai]
    #            - Header=X-Request-Id,\d+
    #            - Method=GET
                - Query=name,zhangsan|lisi
              filters:
                - StripPrefix=1  # 转发之前去掉第一层路径
                  # http://localhost:8020/order-serv/order/add 过虑成
                # http://localhost:8020/order/add
        # 配置 Nacos
        nacos:
          server-addr: 127.0.0.1:8848
          discovery:
            #        server-addr: 127.0.0.1:8848
            username: nacos
            password: nacos
            namespace: public

     

     

  • 相关阅读:
    Linux_23 DNS 正向解析区域、反向解析区域;主/从;子域;基本安全控制
    Linux_22 加密和解密及OpenSSL
    Linux_21 日志系统、ssh服务、系统安装及系统故障排除
    Linux_20 子网划分
    Akavache简明使用指南
    Oracle存储过程解析XML内容
    docker部署微服务不支持中文字体的解决方案
    Three.js
    Three.js
    [Linux] vim状态栏配置
  • 原文地址:https://www.cnblogs.com/mingforyou/p/15781922.html
Copyright © 2020-2023  润新知