天天看點

Gateway之過濾器1 局部過濾器2 全局過濾器

過濾器的作用:過濾器就是在請求的過程中,對請求和響應做一些手腳

生命周期:Pre Post

分類:局部過濾器(作用在某一個路由上)  全局過濾器(作用在全部路由上)

在Gateway中,Filter的生命周期隻有兩個:“pre”和“post”。

  • PRE:這種過濾器在請求被路由之前調用。我們可利用這種過濾器實作身份驗證、在叢集中選擇請求的微服務、記錄調試資訊等。
  • POST:這種過濾器在路由到微服務以後執行。這種過濾器可用來為響應添加标準的HTTP Header、收集統計資訊和名額、将響應從微服務發送給用戶端等。
Gateway之過濾器1 局部過濾器2 全局過濾器

目錄

1 局部過濾器

1.1 内置局部過濾器

1.2 内置過濾器的使用

1.3 自定義局部過濾器

2 全局過濾器

2.1 内置的全局過濾器

2.2 自定義全局過濾器

1 局部過濾器

局部過濾器是針對單個路由的過濾器。

1.1 内置局部過濾器

在SpringCloud Gateway中内置了很多不同類型的網關路由過濾器。具體如下:

Gateway之過濾器1 局部過濾器2 全局過濾器
Gateway之過濾器1 局部過濾器2 全局過濾器
Gateway之過濾器1 局部過濾器2 全局過濾器
Gateway之過濾器1 局部過濾器2 全局過濾器

1.2 内置過濾器的使用

下面示例SetStatus過濾器工廠的使用:

第一步:配置檔案中加入過濾器

server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848   # nacos服務端位址
    gateway:
      discovery:
        locator:
          enabled: true # 啟用探測器,讓gateway可以發現nacos中的微服務
      routes: # 路由數組(路由:就是當指定請求滿足什麼條件的時候,轉發到哪個微服務)
        - id: product_route  # 目前路由的辨別,要求唯一。預設uuid
          uri: lb://service-product # lb指的是負載均衡(load balancing),service-product是nacos中微服務的名稱
          order: 1  # 路由的優先級,數字越小級别越高
          predicates: # 斷言(就是路由轉發要滿足的條件)
            - Path=/product-serv/** # 當請求路徑滿足Path指定的規則時,才進行路由轉發
          filters:  # 過濾器,請求在傳遞過程中可以通過過濾器對其進行一定的修改
            - StripPrefix=1 # 轉發之前去掉1層路徑
            - SetStatus=250 # 修改原始響應的狀态碼
           

第二步:啟動測試

Gateway之過濾器1 局部過濾器2 全局過濾器

1.3 自定義局部過濾器

需求:通過過濾器,配置是否在控制台輸出日志資訊,以及是否記錄日志。

第一步:在配置檔案中,添加一個Log的過濾器配置

server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848   # nacos服務端位址
    gateway:
      discovery:
        locator:
          enabled: true # 啟用探測器,讓gateway可以發現nacos中的微服務
      routes: # 路由數組(路由:就是當指定請求滿足什麼條件的時候,轉發到哪個微服務)
        - id: product_route  # 目前路由的辨別,要求唯一。預設uuid
          uri: lb://service-product # lb指的是負載均衡(load balancing),service-product是nacos中微服務的名稱
          order: 1  # 路由的優先級,數字越小級别越高
          predicates: # 斷言(就是路由轉發要滿足的條件)
            - Path=/product-serv/** # 當請求路徑滿足Path指定的規則時,才進行路由轉發
          filters:  # 過濾器,請求在傳遞過程中可以通過過濾器對其進行一定的修改
            - StripPrefix=1 # 轉發之前去掉1層路徑
            - Log=true,false  # 控制日志是否開啟
           

第二步:自定義一個過濾器工廠,實作裡面的方法

package cn.jack.filter;

import lombok.Data;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

@Component
public class LogGatewayFilterFactory extends AbstractGatewayFilterFactory<LogGatewayFilterFactory.Config>{

    public LogGatewayFilterFactory() {
        super(Config.class);
    }

    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("consoleLog", "cacheLog");
    }

    @Override
    public GatewayFilter apply(Config config) {

        return ((exchange, chain) -> {
            if (config.consoleLog) {
                System.out.println("console日志已開啟...");
            }

            if (config.cacheLog) {
                System.out.println("cache日志已開啟...");
            }

            return chain.filter(exchange);
        });
    }

    @Data
    public static class Config{
        private boolean consoleLog;
        private boolean cacheLog;
    }
}
           

第三步:運作測試

Gateway之過濾器1 局部過濾器2 全局過濾器
Gateway之過濾器1 局部過濾器2 全局過濾器

2 全局過濾器

全局過濾器作用于所有路由,無需配置。通過全局過濾器可以實作對權限的統一校驗,安全性驗證等功能。

2.1 内置的全局過濾器

SpringCloud Gateway内部也是通過一系列的内置全局過濾器對整個路由轉發進行處理的。

Gateway之過濾器1 局部過濾器2 全局過濾器

2.2 自定義全局過濾器

示例通過自定義全局過濾器,完成統一的權限校驗。

開發中的鑒權邏輯:

  • 當用戶端第一次請求服務時,服務端對使用者進行資訊認證(登入)
  • 認證通過,将使用者資訊進行加密形成token,傳回給用戶端,作為登入憑證
  • 以後每次請求,用戶端都攜帶認證的token
  • 服務端對token進行解密,判斷是否有效。
Gateway之過濾器1 局部過濾器2 全局過濾器

如下圖,對于驗證使用者是否已經登入及鑒權的過程,可以在網關統一校驗。

校驗的标準就是請求中是否攜帶token憑證,以及token的正确性。

下面我們通過自定義一個GlobalFIlter,去校驗所有請求的請求參數中是否包含“token”,如果不包含請求參數“token”則不轉發路由,否則執行正常邏輯。

package cn.jack.filter;

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

/**
 * 自定義全局過濾器,需要實作GlobalFilter和Ordered接口
 */
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    // 完成鑒權邏輯
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (StringUtils.isEmpty(token)) {
            System.out.println("鑒權失敗。确少token參數。");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        if (!"jack".equals(token)) {
            System.out.println("token無效...");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        // 繼續執行filter鍊
        return chain.filter(exchange);
    }

    // 順序,數值越小,優先級越高
    @Override
    public int getOrder() {
        return 0;
    }
}
           

啟動測試:

Gateway之過濾器1 局部過濾器2 全局過濾器

繼續閱讀