SpringCloud系列教程:微服务的未来(十四)网关登录校验、自定义过滤器GlobalFilter、GatawayFilter

前言

在微服务架构中,API 网关扮演着至关重要的角色,负责路由请求、执行安全验证、流量控制等任务。Spring Cloud Gateway 作为一个强大的网关解决方案,提供了灵活的方式来实现这些功能。

本篇博客将重点介绍如何在 Spring Cloud Gateway 中实现网关登录校验,以及如何利用自定义过滤器(GlobalFilter 和 GatewayFilter)来处理请求和响应。通过这些技术,开发者可以在网关层统一处理认证、授权等功能,同时保持对路由的细粒度控制。


网关登录校验

登录是基于JWT实现的,JWT的校验算法较为复杂,并且需要使用秘钥。如果每个微服务都独立进行JWT校验,会面临两个主要问题:

  • 每个微服务都必须持有JWT的秘钥,这样会带来安全隐患。
  • 每个微服务需要重复编写登录校验和权限验证的代码,增加了开发和维护的复杂度。

网关是所有微服务的统一入口,所有请求都会先经过网关,可以将JWT的校验工作集中到网关中进行处理。这样做能够有效解决上述问题:

  • 秘钥只需在网关和用户服务中存储,避免了在每个微服务中重复存储秘钥的风险。
  • 登录校验功能只需要在网关中实现,简化了开发流程并避免了代码的重复编写。
    Alt
    网络请求处理流程图:
    在这里插入图片描述

在 Spring Cloud 微服务中,如果你想在网关转发请求之前进行登录校验(例如,验证JWT令牌),通常可以通过在网关中配置 全局过滤器(GlobalFilter) 来完成。Spring Cloud Gateway 提供了一种简便的方式来处理这一需求。

实现步骤:

  1. 创建一个全局过滤器
    Spring Cloud Gateway 提供了GlobalFilter接口,你可以通过实现该接口来定义网关请求的拦截和处理逻辑。

  2. 提取并验证 JWT
    在全局过滤器中,提取请求头中的Authorization字段中的JWT令牌,并使用签名密钥验证JWT是否合法。

  3. 决定是否继续转发请求
    根据JWT的有效性,如果令牌合法且未过期,则继续请求的转发。如果无效或过期,则直接返回401 Unauthorized响应。

自定义过滤器

自定义GlobalFilter

网关过滤器有两种,分别是:

  • GatewayFilter:路由过滤器,作用于任意指定的路由;默认不生效,要配置到路由后生效。
  • GlobalFilter:全局过滤器,作用范围是所有路由;声明后自动生效。

两种过滤器的方法签名一致:

/**
 * 处理请求并将其传递给下一个过滤器
 * @param exchange 当前请求的上下文,其中包含request、response等各种数据
 * @param chain 过滤器链,基于它向下传递请求
 * @return 根据返回值标记当前请求是否被完成或拦截,chain.filter(exchange)就放行了。
 */
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);

创建MyGlobalFilter类

package com.hmall.gateway.filters;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class MyGlobalFilter implements GlobalFilter , Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //模拟登录逻辑
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        System.out.println("headers = "+headers);
        //放行
        return chain.filter(exchange);

    }

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

在通常业务过程中GlobalFilter比自定义GatewayFilter更容易实现。

自定义过滤器GatewayFilter

自定义GatewayFilter不是直接实现GatewayFilter,而是实现AbstractGatewayFilterFactory,示例如下:

@Component
public class PrintAnyGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
    @Override
    public GatewayFilter apply(Object config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                // 编写过滤器逻辑
                System.out.println("PrintAny filter执行了");
                // 放行
                return chain.filter(exchange);
            }
        };
    }
}

对应的配置文件application.yaml如下:

spring:
  cloud:
    gateway:
      default-filters:
            - AddRequestHeader=a,b # AddRequestHeader:这个过滤器会将指定的请求头添加到每个请求中。a,b 代表的是要添加的请求头和它的值,a 是请求头的名字,b 是请求头的值。
            - PrintAny=1,2,3 # 注意,这里多个参数以","隔开,将来会按照shortcutFieldOrder()方法返回的参数顺序依次复制

在这里插入图片描述
实现的PrintAnyGatewayFilterFactory类

package com.hmall.gateway.filters;


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.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Component
public class PrintAnyGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {


    @Override
    public GatewayFilter apply(Object config) {
        return new GatewayFilter() {

            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("PrintAny filter执行成功");
                return chain.filter(exchange);
            }
        };
    }
}

如果需要设置对用的优先级,代码如下:

	@Override
    public GatewayFilter apply(Object config) {
        return new OrderedGatewayFilter(new GatewayFilter() {

            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("PrintAny filter执行成功");
                return chain.filter(exchange);
            }
        },1);
    }

当然,这种过滤器还支持配置参数,在PrintAnyGatewayFilterFactory类里面

    // 自定义配置属性,成员变量名称很重要,下面会用到
    @Data
    static class Config{
        private String a;
        private String b;
        private String c;
    }
    // 将变量名称依次返回,顺序很重要,将来读取参数时需要按顺序获取
    @Override
    public List<String> shortcutFieldOrder() {
        return List.of("a", "b", "c");
    }
   	public PrintAnyGatewayFilterFactory(){
		super(Config.class);
	}
    // 返回当前配置类的类型,也就是内部的Config
    @Override
    public Class<Config> getConfigClass() {
        return Config.class;
    }

在这里插入图片描述


总结

  • Spring Cloud Gateway 是一个强大的网关工具,支持多种自定义过滤器。
  • GlobalFilter 是全局过滤器,可以应用于所有路由。
  • GatewayFilter 是路由级别的过滤器,可以对特定路由添加过滤逻辑。
  • 登录校验 可以通过 JWT 令牌等方式在网关中实现,以保证请求的安全性。

通过结合 GlobalFilter 和 GatewayFilter,你可以根据具体的需求为不同的路由应用不同的过滤逻辑,同时保证全局的一致性和可扩展性。

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

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

相关文章

服务化架构 IM 系统之应用 MQ

在微服务化系统中&#xff0c;存在三个最核心的组件&#xff0c;分别是 RPC、注册中心和MQ。 在前面的两篇文章&#xff08;见《服务化架构 IM 系统之应用 RPC》和《服务化架构 IM 系统之应用注册中心》&#xff09;中&#xff0c;我们站在应用的视角分析了普适性的 RPC 和 注…

Linux-C/C++--深入探究文件 I/O (上)(文件的管理、函数返回错误、exit()、_Exit()、_exit())

经过上一章内容的学习&#xff0c;相信各位读者对 Linux 系统应用编程中的基础文件 I/O 操作有了一定的认识和理解了&#xff0c;能够独立完成一些简单地文件 I/O 编程问题&#xff0c;如果你的工作中仅仅只是涉及到一些简单文件读写操作相关的问题&#xff0c;其实上一章的知识…

内网渗透测试工具及渗透测试安全审计方法总结

1. 内网安全检查/渗透介绍 1.1 攻击思路 有2种思路&#xff1a; 攻击外网服务器&#xff0c;获取外网服务器的权限&#xff0c;接着利用入侵成功的外网服务器作为跳板&#xff0c;攻击内网其他服务器&#xff0c;最后获得敏感数据&#xff0c;并将数据传递到攻击者&#xff0…

豆包MarsCode:小C点菜问题

问题描述 思路分析 这道题的核心任务是找出所有不超过给定价格 m 的菜肴中&#xff0c;最常见的菜肴价格&#xff0c;最后返回该价格的出现次数。 1. 题意理解&#xff1a; 给定一个最大价格 m&#xff0c;小C只会选择价格不超过 m 的菜。菜单上有 n 道菜&#xff0c;每道菜…

从Windows通过XRDP远程访问和控制银河麒麟ukey v10服务器,以及多次连接后黑屏的问题

从Windows通过XRDP远程访问和控制银河麒麟ukey v10服务器&#xff0c;以及多次连接后黑屏的问题。 安装 rdp 服务&#xff1a; yum install -y epel-release yum install -y xrdp或者如下&#xff1a; 可以通过下载rpm软件包&#xff0c;然后rpm方式安装。访问xrdp官网https…

【PowerQuery专栏】实现JSON数据的导入

Json 格式数据是在互联网数据格式传输使用的非常频繁的一类数据,图7.44为Json数据格式中比较典型的数据格式。 PowerQuery进行Json数据解析使用的是Json.Document进行数据解析,Json.Document目前有2个参数。 参数1为内容数据,数据类型为二进制类型,值为需要解析的Json数据参…

Java基础(3)

Java 数据类型详解 九、运算符 1. 基本运算符 Java 提供了多种运算符来执行不同的操作&#xff1a; 算术运算符&#xff1a;&#xff08;加&#xff09;、-&#xff08;减&#xff09;、*&#xff08;乘&#xff09;、/&#xff08;除&#xff09;、%&#xff08;取模&…

PostgreSQL学习笔记:PostgreSQL vs MySQL

PostgreSQL 和 MySQL 都是广泛使用的关系型数据库管理系统&#xff0c;它们有以下一些对比&#xff1a; 一、功能特性 1. 数据类型支持 PostgreSQL&#xff1a;支持丰富的数据类型&#xff0c;包括数组、JSON、JSONB、范围类型、几何类型等。对于复杂数据结构的存储和处理非…

Linux下PostgreSQL-12.0安装部署详细步骤

一、安装环境 postgresql-12.0 CentOS-7.6 注意&#xff1a;确认linux系统可以正常连接网络&#xff0c;因为在后面需要添加依赖包。 二、pg数据库安装包下载 下载地址&#xff1a;PostgreSQL: File Browser 选择要安装的版本进行下载&#xff1a; 三、安装依赖包 在要安…

C语言内存之旅:从静态到动态的跨越

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文一 动态内存管理的必要性二 动态…

[STM32 HAL库]串口中断编程思路

一、前言 最近在准备蓝桥杯比赛&#xff08;嵌入式赛道&#xff09;&#xff0c;研究了以下串口空闲中断DMA接收不定长的数据&#xff0c;感觉这个方法的接收效率很高&#xff0c;十分好用。方法配置都成功了&#xff0c;但是有一个点需要进行考虑&#xff0c;就是一般我们需要…

PyTorch使用教程(10)-torchinfo.summary网络结构可视化详细说明

1、基本介绍 torchinfo是一个为PyTorch用户量身定做的开源工具&#xff0c;其核心功能之一是summary函数。这个函数旨在简化模型的开发与调试流程&#xff0c;让模型架构一目了然。通过torchinfo的summary函数&#xff0c;用户可以快速获取模型的详细结构和统计信息&#xff0…

Java模拟路由协议-rip(路由器仿真实验)

前言&#xff1a; 好久不见&#xff0c;有段时间没有写文章了&#xff0c;本篇文章&#xff0c;由Blue我带大家来复现rip协议。我们以 b站湖南教师匠所讲rip的视频中的例子为我这篇文章所模拟的路由路径 如图&#xff1a; 模拟路径 视频&#xff1a;http://【深入浅出计算机网络…

32V/4A,降压DCDC转换器CP8384百分百占空比输出ESOP8封装,可适用HUB等电路设计

特点&#xff1a; ● Supply Voltage Range: 4.1V~32V ● Input voltage up to 40V ● 4A Continuous Output Current ● Up to 95% Output Efficiency ● CC/CV control ● 350kHz Switching Frequency ● Built-in Soft Start ● 100% Maximum Duty Cycle ● No External Com…

缓存、数据库双写一致性解决方案

双写一致性问题的核心是确保数据库和缓存之间的数据同步&#xff0c;以避免缓存与数据库数据不同步的问题&#xff0c;尤其是在高并发和异步环境下。本文将探讨双写一致性面临的主要问题和解决方案&#xff0c;重点关注最终一致性。 本文讨论的是最终一致性问题 双写一致性面…

【学习笔记15】如何在非root服务器中,安装属于自己的redis

一、下载安装包 官网下载黑马程序员给的安装包&#xff08;redis-6.2.6&#xff09; 二、将安装包上传至服务器 我将安装包上传在我的文件夹/home/XXX&#xff0c;指定路径中/src/local/redis/&#xff0c;绝对路径为/home/XXX/src/local/redis/解压安装包 XXXomega:~$ cd …

计算机网络 (51)鉴别

前言 计算机网络鉴别是信息安全领域中的一项关键技术&#xff0c;主要用于验证用户或信息的真实性&#xff0c;以及确保信息的完整性和来源的可靠性。 一、目的与重要性 鉴别的目的是验明用户或信息的正身&#xff0c;对实体声称的身份进行唯一识别&#xff0c;以便验证其访问请…

【大模型】ChatGPT 高效处理图片技巧使用详解

目录 一、前言 二、ChatGPT 4 图片处理介绍 2.1 ChatGPT 4 图片处理概述 2.1.1 图像识别与分类 2.1.2 图像搜索 2.1.3 图像生成 2.1.4 多模态理解 2.1.5 细粒度图像识别 2.1.6 生成式图像任务处理 2.1.7 图像与文本互动 2.2 ChatGPT 4 图片处理应用场景 三、文生图操…

后端:MyBatis

文章目录 1. MyBatis1-1. Mybatis 工具类的封装1-2. Mybatis 通过集合或实体类传递参数-实现插入数据(增)1-3. MyBatis 实现删除数据(删)1-4. MyBatis 实现修改数据(改)1-5. MyBatis 实现查询数据(查) 2. MyBatis 配置文件中的一些标签和属性2-1.environments标签2-2. dataSour…

将 AzureBlob 的日志通过 Azure Event Hubs 发给 Elasticsearch(1.标准版)

问题 项目里使用了 AzureBlob 存储了用户上传的各种资源文件&#xff0c;近期 AzureBlob 的流量费用增长很快&#xff0c;想通过分析Blob的日志&#xff0c;获取一些可用的信息&#xff0c;所以有了这个需求&#xff1a;将存储账户的日志&#xff08;读写&#xff0c;审计&…