Spring Cloud Alibaba-05-Gateway网关-03-过滤器(Filter)使用

Lison <dreamlison@163.com>, v1.0.0, 2023.10.20

Spring Cloud Alibaba-05-Gateway网关-03-过滤器(Filter)使用

文章目录

  • Spring Cloud Alibaba-05-Gateway网关-03-过滤器(Filter)使用
    • 过滤器的简介
      • 什么是过滤器?
      • 过滤器的生命周期
      • 过滤器的分类和作用范围
    • 局部过滤器
      • 内置局部过滤器
      • 自定义局部过滤器
        • 实现自定义过滤器
    • 全局过滤器
      • 内置全局过滤器
      • 自定义全局过滤器
        • 实现一个鉴权过滤器
    • 过滤器执行顺序
    • Gateway 跨域问题处理

过滤器的简介

什么是过滤器?

  • 过滤器就是在请求的传递中对请求和响应做一些手脚。
  • 声明周期 Pre(处理前),Post(处理后)

过滤器的生命周期

Gateway中,Filter的生命周期只有两个,pre和post,

  • PRE :这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等
  • POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP Header,收集统计信息和指标、将响应从微服务发送到客户端。

在这里插入图片描述

过滤器的分类和作用范围

Gateway的Filter从作用范围可分为GatewayFilter与GlobalFliter

  • GatewayFilter: 应用到某个路由或者一个分组的路由上。
  • GlobalFilter: 应用到所有的路由上。

局部过滤器

内置局部过滤器

官方地址文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories

官方文档介绍了各种内置的局部过滤器,包含了案例。

在这里插入图片描述

以 AddResponseHeader为例子,使用这个过滤器

AddResponseHeader=X-Response-Red, Lison

在这里插入图片描述

自定义局部过滤器

实现自定义过滤器

需求配置Log,第一个参数控制台是否打印,第二个参数缓存日志是否打印

  1. 先在配置文件中进行配置
spring:
  cloud:
    gateway:
      routes:
       - id: spring_service
        uri: http://localhost:18001
        predicates:
         	- Method=GET
        filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
          - StripPrefix=1 # 转发之前去掉1层路径
          - Log=true,false #开启缓存日志和控制台日志,第一个参数控制台日志,第二个参数缓存日志
 
 
  1. 编写内部过滤器
package com.lison.springcloudservice.config.filter;

import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

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


/**
 * @className: com.lison.springcloudservice.config.filter-> LogGatewayFilterFactory
 * @description: 自定义的局部过滤器 1. 类名必须是配置+GatewayFilterFactory 2. 必须继承AbstractGatewayFilterFactory
 * @author: Lison
 * @createDate: 2023-10-20
 */
@Component
public class LogGatewayFilterFactory extends AbstractGatewayFilterFactory<LogGatewayFilterFactory.Config> {

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

    //过滤器的逻辑
    @Override
    public GatewayFilter apply(Config config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                //获取封装 HttpRequest 后的对象
                ServerHttpRequest request = exchange.getRequest();
                //获取封装 HttpResponse 后的对象
                ServerHttpResponse response = exchange.getResponse();
                System.out.println("-------请求到来,经过全局 Filter 处理-------");
                if (config.isCacheLog()) {
                    System.out.println("cacheLog开启了-------");
                }
                if (config.isConsoleLog()) {
                    System.out.println("consoleLog开启了-------");
                }
                Mono<Void> mono = chain.filter(exchange);
                return mono;
            }
        };
    }

    //用于接收参数,需要和配置文件里的参数对应
    @Override
    public List<String> shortcutFieldOrder() {
        return Arrays.asList("consoleLog", "cacheLog");
    }

    public static class Config {
        private boolean consoleLog;
        private boolean cacheLog;

        public boolean isConsoleLog() {
            return consoleLog;
        }

        public void setConsoleLog(boolean consoleLog) {
            this.consoleLog = consoleLog;
        }

        public boolean isCacheLog() {
            return cacheLog;
        }

        public void setCacheLog(boolean cacheLog) {
            this.cacheLog = cacheLog;
        }

        @Override
        public String toString() {
            return "Config{" +
                    "consoleLog=" + consoleLog +
                    ", cacheLog=" + cacheLog +
                    '}';
        }
    }
}

3、启动网关测试,可以看到consoleLog打印了。

-------请求到来,经过局部 Log Filter 处理-------
consoleLog开启了-------

总结:自定义局部过滤器

  1. 类名必须是配置+GatewayFilterFactory
  2. 必须继承AbstractGatewayFilterFactory

全局过滤器

全局过滤器不和具体的路由关联,作用在所有路由上,不需要配置。通过全局过滤器可以实现对权限的统一校验,安全性校验等。

内置全局过滤器

在这里插入图片描述

我们只需要记住以下几个常用的即可

  1. AddRequestHeader:给当前请求添加一个请求头,例如 - AddRequestHeader=color, red 就表示给请求头总加入一个键值对 color=red.

  2. AddRequestParameter:表示给请求加一个参数,例如 - AddRequestParameter=name, cyk 也就意味着后端对应的接口因该提供一个参数去接收

  3. AddResponseHeader:给响应结果中添加一个响应头,例如 - AddResponseHeader=name,cyk 那么后端在返回响应的时候就会在响应头中添加 name=cyk 的键值对.

  4. PrefixPath:表示给请求的 url 中添加前缀,例如 - PrefixPath=/user ,那么如果你原本的请求是路径是 localhost:8080/list ,那么经过 PrefixPath 处理之后,就会变成localhost:8080/user/list

  5. StripPrefix:表示给请求的 url 中去表指定的 n 个前缀路由,例如 - StripPrefix=2 那么如果你原本的请求是路由是 /user/list/get ,那么经过 StripPrefix 处理后,就会变成 /get.

Spring提供了31种不同的路由过滤器工厂,这些需要什么都可以直接去官网上copy,不用刻意去记~

自定义全局过滤器

内置的过滤器已经实现了大部分的功能,但是对应企业开发的一些业务功能处理,还是需要我们自己编写过滤器来实现的。
开发中的鉴权逻辑

  • 当客户端第一次请求服务时,服务端对用户进行认证(登录)
  • 认证通过后,将用户信息进行加密形成token,返回给客户端,作为登录凭证
  • 以后每次请求,客户端都携带认证的token
  • 服务端对token进行解密,判断是否有效
实现一个鉴权过滤器
package com.lison.springcloudservice.config.filter;

import org.apache.commons.lang.StringUtils;
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.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * @className: com.lison.springcloudservice.config.filter-> AuthGlobalFilter
 * @description:  自定义鉴权全局过滤器  必须实现GlobalFilter和Ordered两个接口,并实现接口的方法
 * @author: Lison
 * @createDate: 2023-10-20
 */
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    //过滤器逻辑
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取封装 HttpRequest 后的对象
        ServerHttpRequest request = exchange.getRequest();
        //获取封装 HttpResponse 后的对象
        ServerHttpResponse response = exchange.getResponse();
        System.out.println("-------请求到来,经过全局 Filter 处理-------");
        //对请求做处理......
        Mono<Void> filter = chain.filter(exchange);//放行 filter 向后执行:也就意味接下来进入到具体的微服务中(例如 user 微服务)
        //对响应做处理......
        System.out.println("-------响应回来,经过全局 Filter 处理-------");

        //将token放在参数里面传递只是一个演示,正常的业务逻辑当然不是这样做,这里只是为了演示。
        String token = request.getQueryParams().getFirst("token");
        if(!StringUtils.equals("admin",token)){
            System.out.println("认证失败");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);//401表示未认证
            return exchange.getResponse().setComplete();
        }

        //chain.filter继续传递向下
        return filter;
    }

    //返回值越小,优先级越高
    @Override
    public int getOrder() {
        return 0;
    }
}

2、启动网关测试,可以看到日志打印了。

http://localhost:18003/spring_service/getServerProd

-------请求到来,经过全局 Filter 处理-------
-------响应回来,经过全局 Filter 处理-------
认证失败


http://localhost:18003/spring_service/getServerProd?token=admin
-------请求到来,经过全局 Filter 处理-------
-------响应回来,经过全局 Filter 处理-------
-------请求到来,经过局部 Log Filter 处理-------
consoleLog开启了-------

总结:

  1. 实现 GlobalFilter 接口,重写 filter 方法
  2. 添加 @Order 注解或实现 Ordered 接口
  3. 编写处理逻辑

过滤器执行顺序

请求进入网关会碰到三类过滤器(当前路由的过滤器、DefaultFilter、GlobalFilter),然后合并到一个过滤器集合中,排序后一次执行每一个过滤器,那么他的一个执行顺序是怎样的呢?

执行规则

1.order值越小,优先级越高(GlobalFilter由我们自定义,路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增)

2.当order值一样时,顺序是defaultFilter > 路由过滤器 > 全局过滤器。

Gateway 跨域问题处理

跨域:域名不一致就是跨域,主要包括:

域名不同: www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com
域名相同,端口不同:localhost:8080和localhost8081
跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

解决方案:CORS

网关处理跨域采用的同样是CORS方案,并且只需要简单配置即可实现(这些东西不用记住,需要的时候 CV 就可以)

spring:
  cloud:
    gateway:
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求(2.4版本以后需要更改为 allowedOriginPatterns ) 
              - "http://localhost:18001"
              - "http://www.taobao.com"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期(为例减少性能损耗,在有效时间内,浏览器将不在发起询问,直接放行通过)

当然也可以不用分的这么细,可以直接用下面整个通用的配置即可.

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedMethods: "*"
            allowedHeaders: "*"
            allowedOriginPatterns: "*"
            allowCredentials: true

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/403616.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

从 Elasticsearch 到 Apache Doris,统一日志检索与报表分析,360 企业安全浏览器的数据架构升级实践

导读&#xff1a;随着 360 企业安全浏览器用户规模的不断扩张&#xff0c;浏览器短时间内会产生大量的日志数据。为了提供更好的日志数据服务&#xff0c;360 企业安全浏览器设计了统一运维管理平台&#xff0c;并引入 Apache Doris 替代了 Elasticsearch&#xff0c;实现日志检…

HarmonyOS4.0系统性深入开发36 媒体查询(mediaquery)

媒体查询&#xff08;mediaquery&#xff09; 概述 媒体查询作为响应式设计的核心&#xff0c;在移动设备上应用十分广泛。媒体查询可根据不同设备类型或同设备不同状态修改应用的样式。媒体查询常用于下面两种场景&#xff1a; 针对设备和应用的属性信息&#xff08;比如显…

Prometheus+Grafana 监控

第1章Prometheus 入门 Prometheus 受启发于 Google 的 Brogmon 监控系统&#xff08;相似的 Kubernetes 是从 Google的 Brog 系统演变而来&#xff09;&#xff0c;从 2012 年开始由前 Google 工程师在 Soundcloud 以开源软件的形式进行研发&#xff0c;并且于 2015 年早期对外…

【FPGA】VHDL:小型出勤系统设计

附源代码&#xff0c;一定能实现&#xff01; 目录 EDA设计练习题&#xff1a; 实验要求如下&#xff1a; 思路分析&#xff1a; 代码 99进制计数器 码转换 顶层文件 特别注意 测试 编译通过 结果展示 RTL视图 技术映射视图 软件&#xff1a;Quartus II 13.0 (64…

【打工日常】使用docker部署StackEdit编辑器-Markdown之利器

一、StackEdit介绍 StackEdit一款强大的在线Markdown编辑器&#xff0c;不仅具备卓越的写作功能&#xff0c;还支持实时预览、多设备同步等特性。 很多时候基于安全和信息保密的关系&#xff0c;建议放在自己的服务器或者本地linux去运行&#xff0c;这样会比较省心。 二、本次…

使用k-近邻算法改进约会网站的配对效果(kNN)

目录 谷歌笔记本&#xff08;可选&#xff09; 准备数据&#xff1a;从文本文件中解析数据 编写算法&#xff1a;编写kNN算法 分析数据&#xff1a;使用Matplotlib创建散点图 准备数据&#xff1a;归一化数值 测试算法&#xff1a;作为完整程序验证分类器 使用算法&…

MybatisPlus基础入门以及入门案例

目录 一、MyBatisPlus简介 二、MyBatisPlus特性 三、MyBatisPlus支持的数据库 四、框架结构 五、入门案例 1.开发环境 2.创建数据库及表 3.创建Spring Boot工程 4.导入依赖 5.项目结构 6.配置application.yml 7.配置SpringBoot启动类 8.添加实体类 9.添加mapper接口 10.测试…

vue后台管理添加水印简单方式watermark-package

详情参考:https://www.npmjs.com/package/watermark-package 示例方法 <el-button type"primary" click"AddWatermark">添加水印</el-button><el-button type"primary" click"RemoveWatermark">清除水印</el-but…

MKdocs添加顶部公告栏

效果如图&#xff1a; docs/overrides下新建main.html &#xff0c;针对main.html文件 树状结构如下: $ tree -a . ├── .github │ ├── .DS_Store │ └── workflows │ └── PublishMySite.yml ├── docs │ └── index.md │ └──overrides │…

领域驱动设计在互联网业务开发中的实践

至少30年以前&#xff0c;一些软件设计人员就已经意识到领域建模和设计的重要性&#xff0c;并形成一种思潮&#xff0c;Eric Evans将其定义为领域驱动设计&#xff08;Domain-Driven Design&#xff0c;简称DDD&#xff09;。在互联网开发“小步快跑&#xff0c;迭代试错”的大…

数字孪生城市及其他应用场景应用

数字孪生的“虚拟副本”让城市治理不再盲人摸象。 从城市治理的角度来看&#xff0c;数字孪生城市相当于真实世界的“操作系统”&#xff0c;有了它就可以远程对城市的每一个角落进行监测、智慧调度&#xff0c;无论是街道、社区&#xff0c;还是商场、变电站乃至城市排水系统…

使用 JMeter 生成测试数据对 MySQL 进行压力测试

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

【C语言基础教程】getline函数与临时文件

文章目录 前言一、getline函数1.1 为什么需要这个函数1.2 getline函数的使用1.3 使用示例 二、临时文件2.1 临时文件的使用2.2 示例代码 总结 前言 在C语言编程中&#xff0c;处理文本文件是一个常见的任务。然而&#xff0c;有时候我们需要处理那些我们不想在磁盘上创建的临时…

Qwen-VL本地化部署及微调实践

Qwen-VL本地化部署及微调实践 创建虚拟环境模型部署下载模型文件下载项目代码安装python依赖环境修改web_demo_mm.py及openai_api.py的部分代码启动测试 模型微调环境部署数据准备微调 问题 创建虚拟环境 conda create -name vl python3.10.8模型部署 下载模型文件 https://…

React学习——快速上手

文章目录 初步模块思维 初步 https://php.cn/faq/400956.html 1、可以手动使用npm来安装各种插件&#xff0c;来从头到尾自己搭建环境。 如&#xff1a; npm install react react-dom --save npm install babel babel-loader babel-core babel-preset-es2015 babel-preset-rea…

从MATLAB到MWORKS,科学计算与系统建模仿真平台的中国选项

“中国需要自主的科学计算与系统建模仿真平台。” 工业软件是所有复杂系统研发设计、仿真验证和数字制造的必备工具&#xff0c;已经成为衡量一个国家工业竞争力的核心指标。在传统工业软件领域&#xff0c;我们一直处于落后状态&#xff0c;尤其是研发设计类工业软件&#xff…

uniapp开发微信小程序跳转到另一个小程序中

注意&#xff1a;一开始我的云上务工模块是单独的tabbar界面&#xff0c;但是小程序跳转好像不能直接点击tabbar进行&#xff0c;所以我将这里改成了点击首页中的按钮进行跳转 点击这里进行小程序跳转 目录 基础讲解 uniapp小程序跳转的两个方法 调用说明&#xff08;半屏跳转…

助力国产BMS管理芯片品牌发展,世强硬创获迈巨微电子授权代理

作为电池的核心半导体器件&#xff0c;BMS电池管理芯片在电动化时代的需求持续旺盛&#xff0c;并迎来了快速迭代的时期。 为满足电动自行车、AGV等市场对BMS电池管理芯片的需求&#xff0c;世强先进&#xff08;深圳&#xff09;科技股份有限公司&#xff08;下称“世强先进”…

记阿里云mysql丢表丢数据的实践记录

第一时间挂工单&#xff0c;联系工程师指引&#xff0c;现在回过来想&#xff0c;第一时间要确认发生时间。 1.通过性能视图&#xff08;马后炮的总结&#xff0c;实际凭记忆恢复了三四次才找到数据&#xff09; 2.先恢复数据 通过Navicat工具&#xff0c;结构同步&#xff0…

动态绑定样式,uniapp,用三元运算动态绑定多个class类样式,动态绑定的样式可以和原始样式共存

介绍 | uni-app官网 vue、uniapp中动态添加绑定style、class 9种方法实现_vue style动态绑定-CSDN博客 uniapp使用三元运算符动态绑定元素的style样式_uniapp style动态绑定-CSDN博客 对象写法,可以写多个class类 class类的名字&#xff1a;判断条件&#xff0c;最后结果只有…