Gateway之过滤器

过滤器的作用:过滤器就是在请求的过程中,对请求和响应做一些手脚

生命周期:Pre Post

分类:局部过滤器(作用在某一个路由上)  全局过滤器(作用在全部路由上)

在Gateway中,Filter的生命周期只有两个:“pre”和“post”。

  • PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。

  • POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

目录

1 局部过滤器

1.1 内置局部过滤器

1.2 内置过滤器的使用

1.3 自定义局部过滤器

2 全局过滤器

2.1 内置的全局过滤器

2.2 自定义全局过滤器


1 局部过滤器

局部过滤器是针对单个路由的过滤器。

1.1 内置局部过滤器

在SpringCloud Gateway中内置了很多不同类型的网关路由过滤器。具体如下:

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 # 修改原始响应的状态码

第二步:启动测试

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;
    }
}

第三步:运行测试

2 全局过滤器

全局过滤器作用于所有路由,无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功能。

2.1 内置的全局过滤器

SpringCloud Gateway内部也是通过一系列的内置全局过滤器对整个路由转发进行处理的。

2.2 自定义全局过滤器

示例通过自定义全局过滤器,完成统一的权限校验。

开发中的鉴权逻辑:

  • 当客户端第一次请求服务时,服务端对用户进行信息认证(登录)
  • 认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证
  • 以后每次请求,客户端都携带认证的token
  • 服务端对token进行解密,判断是否有效。

如下图,对于验证用户是否已经登录及鉴权的过程,可以在网关统一校验。

校验的标准就是请求中是否携带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;
    }
}

启动测试:

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值