当前位置: 首页 > news >正文

springcloud-gateway-2-鉴权

目录

一、跨域安全设置

二、GlobalFilter实现全局的过滤与拦截。

三、GatewayFilter单个服务过滤器

1、原理-官方内置过滤器

2、自定义过滤器-TokenAuthGatewayFilterFactory

3、完善TokenAuthGatewayFilterFactory的功能

4、每一个服务编写一个或多个过滤器,实现鉴权的需要

四、总结


续前篇,介绍了gateway中实现了动态路由转发功能以后,本篇将介绍何在spring gateway中实现鉴权的功能。

鉴权目的就是为了安全。仅开放给指定的有权限的合适的人资源。网关在提供统一的路由解析的同时,会提供统一和token认证,统一的加解密,统一的身份认证等功能。

一般作为网关,需要转发的服务较多,在服务级权限分类上,可能有这么几种类理:

  • 直接放行,比如静态资源。当然这种一般建议直接在nginx跳转,减少网关流量。但是还是会有一些比如login等,需要直接放行的接口。
  • 需要jwt等TOKEN验证。在请求头中携带token字段,用来验证是否有合适的身份。这个用得比较多,通常会把token存到redis中。
  • 需要sign验证。在请求头或url参数中携带sign验证字段。可能采用md5等计算方法。
  • 需要jwt验证,同时需要对报文进行加密传输。比如采用rsa\m3等加密。
  • 除此之外还有黑名单。需要全局生效

针对上面的需求,我们就可以利用下面这两个过滤器进行分类实现: 

  • GlobalFilter 全局过滤器
  • GatewayFilter 将应用到单个路由或者同一个分组中的路由上

一、跨域安全设置

如果生产环境限定域名的,可以配置。如果前后端分离的,一般要设置允许所有的网站访问。

    gateway:globalcors:cors-configurations:'[/**]': # 匹配所有请求allowedOrigins: "*" #跨域处理 允许所有的域allowedMethods: # 支持的方法- GET- POST- PUT- DELETE

二、GlobalFilter实现全局的过滤与拦截。

利用GlobalFilter实现全局过滤-黑名单功能,新建一个类,继承GlobalFilter就好了:

package com.iuyun.gateway.filter;import com.iuyun.gateway.services.IpService;
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.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import javax.annotation.Resource;
import java.util.Objects;/*** 这是自定义的全局过滤器* 1、 黑名单禁止访问* 2、 ...*/
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {@ResourceIpService ipService;@Overridepublic int getOrder() {// TODO Auto-generated method stubreturn -1;   // 数字越小,优先级越高。定义-1为最高优先级}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();System.out.println("MyGlobalFilter: uri:" + request.getURI() );// 获取请求ipString ip = Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress();// 1 调用服务,检查是否在黑名单池内.如果是黑名单,则中断。if (ipService.isIpBlocked(ip)) {exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);return exchange.getResponse().setComplete();}// 2 执行其他全局服务// 3 放行return chain.filter(exchange);}}

调用到的方法(模拟): 


@Service
public class IpService {/***  根据IP地址查询数据库中的黑白名单列表,判断是否被阻止* */public boolean isIpBlocked(String ipAddress) {System.out.println("ip:"+ipAddress);// 将ip去redis或者数据库中查找,是否在黑名单内。//    return count >0; // 只要出现条数大于0,则表示在默名单内// 这里面是模拟,写死了return ipAddress.equals("192.168.2.3");}
}

 测试:我们从不同IP来访问不同的服务,可以看到都会被执行:

 当IP在黑名单内时,会返回403:

三、GatewayFilter单个服务过滤器

将应用到单个路由或者同一个分组中的路由上。

1、原理-官方内置过滤器

我们先看一下官方的示例:

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - AddResponseHeader=X-Response-Red, Blue
表示使用过滤器AddResponseHeader,=后面的是参数,它接收一个名称和一个正则表式。

那我们去看看它是怎么实现的:

看了一下其他的filterFactory,都差不多,简单总结一下:

1、命名:PrefixPathGatewayFilterFactory => XXXXGatewayFilterFactory

2、继承抽象类 AbstractGatewayFilterFactory<PrefixPathGatewayFilterFactory.Config> 

3、重写方法GatewayFilter apply(Config config)

我们如果照抄一份,是不是就可以实现自定义过滤器了呢?下面我就来试一下。

2、自定义过滤器-TokenAuthGatewayFilterFactory

1)编写一个GatewayFilterFactory(复制AddResponseHeaderFilterFactory的内容,改个名)


@Component
public class TokenAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic GatewayFilter apply(NameValueConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String value = ServerWebExchangeUtils.expand(exchange, config.getValue());exchange.getResponse().getHeaders().add(config.getName(), value);System.out.println("config.getName():" + config.getName());System.out.println("value:" + value);return chain.filter(exchange);}@Overridepublic String toString() {return filterToStringCreator(TokenAuthGatewayFilterFactory.this).append(config.getName(), config.getValue()).toString();}};}}

2)application配置

3)重启,看一下测试效果

 

先走了全局过滤器,然后这个se-a服务走了这个filter,打印了变量。

这就证明了可以这样实现自定义过滤器,那么,我们在gateway中做任何的校验就方便了。且predicates和filters是可以使用多个进行组合的:

filters: - StripPrefix=1- TokenAuth=jwt,Hello- AddResponseHeader=jwt,Hello1

这样就使用了三个filter。

3、完善TokenAuthGatewayFilterFactory的功能

(这个过程就根据自己的需要进行编写吧,比如,采用RSA加密,sm3加密,验证JWT等)

这里我模拟一个需求如下:

每次请求必须在请求头或url参数中传递一个token字段。

如果没有直接拒绝请求.如果token不对,返回401。

只有token正确,才放行,并在请求头添加一个userId字段传递给被调用的微服务。

要想实现直接拒绝不响应,可以使用predicatie,不符合条件就返回404了

- id: service-auri: lb://service-a # lb:服务名称。表示调用nacos注册的服务名称为service-b的服务predicates:- Path=/se-a/**- Header=token,\d+filters: - StripPrefix=1  - TokenAuth=jwt,Hello

但是这样并不友好,有统一返回值是现在流行的做法。且万一在prdicates中忘记加这个Header了,在filter中就因为没有token字段而出错。所以为了防止出错在filter还是要再进行一次token是否为空的校验,那么就干脆都在filter中实现吧。


@Component
public class TokenAuthGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {@Overridepublic GatewayFilter apply(NameValueConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String value = ServerWebExchangeUtils.expand(exchange, config.getValue());  // config.getValue()  config.getName()String headerToken = exchange.getRequest().getHeaders().getFirst("token");String urlToken = exchange.getRequest().getQueryParams().getFirst("token");// 优先使用header中的token,其次是url中的token,如果没有则继续为nullString reqToken =StringUtils.isBlank(headerToken)? urlToken:headerToken;// 检查token是否存在且正确,一般都需要去调auth服务,从数据库或redis拿到密码并校验String userId = TokenCheck.JwtCheck(reqToken);if(StringUtils.isBlank(reqToken) || StringUtils.isBlank(userId)){// 返回状态码401表示未授权exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}// 运行到这里,表示token计算正确。将UserID添加到header进行传递ServerHttpRequest request = exchange.getRequest().mutate().headers(httpHeaders -> httpHeaders.add("userId",userId)).build();return chain.filter(exchange.mutate().request(request).build());}@Overridepublic String toString() {return filterToStringCreator(TokenAuthGatewayFilterFactory.this).append(config.getName(), config.getValue()).toString();}};}}
@Component
public class TokenCheck {public static String JwtCheck(String token){// 去redis获取是否存在这个token,如果不存在,则表示未登陆或登陆已过期。// 如果没存到redis,则这里要粗数据库调user表,查询用户的密码,并调用jwt的方法计算密码是否正确// 这里做模拟,先写死。如果正确,返回一个userId =if(!StringUtils.isBlank(token) && !token.equals("jwt11234")){return null;}else{// 这里写死,返回一个userIDreturn "admin";}}
}

4、每一个服务编写一个或多个过滤器,实现鉴权的需要

也可以多个服务使用同一个过滤器。

四、总结

由于本篇重点是讲gateway中如何实现鉴权,所以并未展开介绍。在上面的示例中,我们并没有真的实现jwt验证等,只是做了一个固定值的返回。后面我们将继续介绍实现jwt的验证。

相关文章:

springcloud-gateway-2-鉴权

目录 一、跨域安全设置 二、GlobalFilter实现全局的过滤与拦截。 三、GatewayFilter单个服务过滤器 1、原理-官方内置过滤器 2、自定义过滤器-TokenAuthGatewayFilterFactory 3、完善TokenAuthGatewayFilterFactory的功能 4、每一个服务编写一个或多个过滤器&#xff0c…...

实现一个最简单的内核

更好的阅读体验&#xff0c;请点击 YinKai s Blog | 实现一个最简单的内核。 ​ 这篇文章带大家实现一个最简单的操作系统内核—— Hello OS。 PC 机的引导流程 ​ 我们这里将借助 Ubuntu Linux 操纵系统上的 GRUB 引导程序来引导我们的 Hello OS。 ​ 首先我们得了解一下&a…...

2024华为OD机试真题指南宝典—持续更新(JAVAPythonC++JS)【彻底搞懂算法和数据结构—算法之翼】

PC端可直接搜索关键词 快捷键&#xff1a;CtrlF 年份关键字、题目关键字等等 注意看本文目录-快速了解本专栏 文章目录 &#x1f431;2024年华为OD机试真题&#xff08;马上更新&#xff09;&#x1f439;2023年华为OD机试真题&#xff08;更新中&#xff09;&#x1f436;新…...

【12.23】转行小白历险记-算法02

不会算法的小白不是好小白&#xff0c;可恶还有什么可以难倒我这个美女的&#xff0c;不做花瓶第二天&#xff01; 一、螺旋矩阵 59. 螺旋矩阵 II - 力扣&#xff08;LeetCode&#xff09; 1.核心思路&#xff1a;确定循环的路线&#xff0c;左闭右开循环&#xff0c;思路简…...

k8s部署nginx-ingress服务

k8s部署nginx-ingress服务 经过大佬的拷打&#xff0c;终于把这块的内容配置完成了。 首先去 nginx-ingress官网查看相关内容。 核心就是这个&#xff1a; kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/prov…...

SpringBoot Elasticsearch全文搜索

文章目录 概念全文搜索相关技术Elasticsearch概念近实时索引类型文档分片(Shard)和副本(Replica) 下载启用SpringBoot整合引入依赖创建文档类创建资源库测试文件初始化数据创建控制器 问题参考 概念 全文搜索&#xff08;检索&#xff09;&#xff0c;工作原理&#xff1a;计算…...

Python 常用模块re

Python 常用模块re 【一】正则表达式 【1】说明 正则表达式是一种强大的文本匹配和处理工具&#xff0c;主要用于字符串的模式匹配、搜索和替换。正则表达式测试网址&#xff1a;正则表达式在线测试 正则表达式手册&#xff1a;正则表达式手册 【2】字符组 字符转使用[]表…...

【华为OD题库-106】全排列-java

题目 给定一个只包含大写英文字母的字符串S&#xff0c;要求你给出对S重新排列的所有不相同的排列数。如:S为ABA&#xff0c;则不同的排列有ABA、AAB、BAA三种。 解答要求 时间限制:5000ms,内存限制:100MB 输入描述 输入一个长度不超过10的字符串S&#xff0c;确保都是大写的。…...

Three.js 详细解析(持续更新)

1、简介&#xff1b; Three.js依赖一些要素&#xff0c;第一是scene&#xff0c;第二是render&#xff0c;第三是carmea npm install --save three import * as THREE from "three"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js&quo…...

Unity中Shader平移矩阵

文章目录 前言方式一&#xff1a;对顶点本地空间下的坐标进行相加平移1、在属性面板定义一个四维变量记录在 xyz 上平移多少。2、在常量缓冲区进行申明3、在顶点着色器中&#xff0c;在进行其他坐标转化之前&#xff0c;对模型顶点本地空间下的坐标进行转化4、我们来看看效果 方…...

python dash 的学习笔记1

dash 用python开发web界面 https://dash.plotly.com/ 官方上支持jula F# python一类。当然我只会python只学习python中使用dash. 要做一个APP&#xff0c;用php,java以及.net都可以写&#xff0c;只所有选择python是因为最近在用这一个。同时也发现python除了慢全是优点。 资料…...

SQLITE如何同时查询出第一条和最后一条两条记录

一个时间记录表&#xff0c;需要同时得到整个表或一段时间内第一条和最后一条两条记录&#xff0c;按如下方法会提示错误&#xff1a;ORDER BY clause should come after UNION not before select * from sdayXX order by op_date asc limit 1 union select * from sday…...

四、ensp配置ftp服务器实验

文章目录 实验内容实验拓扑操作步骤配置路由器为ftp server 实验内容 本实验模拟企业网络。PC-1为FTP 用户端设备&#xff0c;需要访问FTP Server&#xff0c;从服务器上下载或上传文件。出于安全角度考虑&#xff0c;为防止服务器被病毒文件感染&#xff0c;不允许用户端直接…...

VS2020使用MFC开发一个贪吃蛇游戏

背景&#xff1a; 贪吃蛇游戏 按照如下步骤实现:。初始化地图 。通过键盘控制蛇运动方向&#xff0c;注意重新设置运动方向操作。 。制造食物。 。让蛇移动&#xff0c;如果吃掉食物就重新生成一个食物&#xff0c;如果会死亡就break。用蛇的坐标将地图中的空格替换为 #和”将…...

【经典LeetCode算法题目专栏分类】【第9期】深度优先搜索DFS与并查集:括号生成、岛屿问题、扫雷游戏

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推荐--…...

字符设备驱动开发-注册-设备文件创建

一、字符设备驱动 linux系统中一切皆文件 1、应用层&#xff1a; APP1 APP2 ... fd open("led驱动的文件"&#xff0c;O_RDWR); read(fd); write(); close(); 2、内核层&#xff1a; 对灯写一个驱动 led_driver.c driver_open(); driver_read(); driver_write(…...

TrustZone之可信操作系统

有许多可信内核&#xff0c;包括商业和开源的。一个例子是OP-TEE&#xff0c;最初由ST-Ericsson开发&#xff0c;但现在是由Linaro托管的开源项目。OP-TEE提供了一个功能齐全的可信执行环境&#xff0c;您可以在OP-TEE项目网站上找到详细的描述。 OP-TEE的结构如下图所示&…...

java定义三套场景接口方案

一、背景 在前后端分离开发的背景下&#xff0c;后端java开发人员现在只需要编写接口接口。特别是使用微服务开发的接口。resful风格接口。那么一般后端接口被调用有下面三种场景。一、不需要用户登录的接口调用&#xff0c;第二、后端管理系统接口调用&#xff08;需要账号密…...

idea连接数据库,idea连接MySQL,数据库驱动下载与安装

文章目录 普通Java工程先创建JAVA工程JDBC连接数据库测试连接 可视化连接数据库数据库驱动下载与安装常用的数据库驱动下载MySQL数据库Oracle数据库SQL Server 数据库PostgreSQL数据库 下载MySQL数据库驱动JDBC连接各种数据库的连接语句MySQL数据库Oracle数据库DB2数据库sybase…...

Redis-实践知识

转自极客时间Redis 亚风 原文视频&#xff1a;https://u.geekbang.org/lesson/535?article681062 Redis最佳实践 普通KEY Redis 的key虽然可以自定义&#xff0c;但是最好遵循下面几个实践的约定&#xff1a; 格式&#xff1a;[业务名称]:[数据名]:[id] 长度不超过44字节 不…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...