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、每一个服务编写一个或多个过滤器,…...

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

2024华为OD机试真题指南宝典—持续更新(JAVAPythonC++JS)【彻底搞懂算法和数据结构—算法之翼】
PC端可直接搜索关键词 快捷键:CtrlF 年份关键字、题目关键字等等 注意看本文目录-快速了解本专栏 文章目录 🐱2024年华为OD机试真题(马上更新)🐹2023年华为OD机试真题(更新中)🐶新…...

【12.23】转行小白历险记-算法02
不会算法的小白不是好小白,可恶还有什么可以难倒我这个美女的,不做花瓶第二天! 一、螺旋矩阵 59. 螺旋矩阵 II - 力扣(LeetCode) 1.核心思路:确定循环的路线,左闭右开循环,思路简…...
k8s部署nginx-ingress服务
k8s部署nginx-ingress服务 经过大佬的拷打,终于把这块的内容配置完成了。 首先去 nginx-ingress官网查看相关内容。 核心就是这个: kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/prov…...

SpringBoot Elasticsearch全文搜索
文章目录 概念全文搜索相关技术Elasticsearch概念近实时索引类型文档分片(Shard)和副本(Replica) 下载启用SpringBoot整合引入依赖创建文档类创建资源库测试文件初始化数据创建控制器 问题参考 概念 全文搜索(检索),工作原理:计算…...
Python 常用模块re
Python 常用模块re 【一】正则表达式 【1】说明 正则表达式是一种强大的文本匹配和处理工具,主要用于字符串的模式匹配、搜索和替换。正则表达式测试网址:正则表达式在线测试 正则表达式手册:正则表达式手册 【2】字符组 字符转使用[]表…...
【华为OD题库-106】全排列-java
题目 给定一个只包含大写英文字母的字符串S,要求你给出对S重新排列的所有不相同的排列数。如:S为ABA,则不同的排列有ABA、AAB、BAA三种。 解答要求 时间限制:5000ms,内存限制:100MB 输入描述 输入一个长度不超过10的字符串S,确保都是大写的。…...
Three.js 详细解析(持续更新)
1、简介; Three.js依赖一些要素,第一是scene,第二是render,第三是carmea npm install --save three import * as THREE from "three"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js&quo…...

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

python dash 的学习笔记1
dash 用python开发web界面 https://dash.plotly.com/ 官方上支持jula F# python一类。当然我只会python只学习python中使用dash. 要做一个APP,用php,java以及.net都可以写,只所有选择python是因为最近在用这一个。同时也发现python除了慢全是优点。 资料…...
SQLITE如何同时查询出第一条和最后一条两条记录
一个时间记录表,需要同时得到整个表或一段时间内第一条和最后一条两条记录,按如下方法会提示错误: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 用户端设备,需要访问FTP Server,从服务器上下载或上传文件。出于安全角度考虑,为防止服务器被病毒文件感染,不允许用户端直接…...

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

【经典LeetCode算法题目专栏分类】【第9期】深度优先搜索DFS与并查集:括号生成、岛屿问题、扫雷游戏
《博主简介》 小伙伴们好,我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推荐--…...

字符设备驱动开发-注册-设备文件创建
一、字符设备驱动 linux系统中一切皆文件 1、应用层: APP1 APP2 ... fd open("led驱动的文件",O_RDWR); read(fd); write(); close(); 2、内核层: 对灯写一个驱动 led_driver.c driver_open(); driver_read(); driver_write(…...

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

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

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

Redis-实践知识
转自极客时间Redis 亚风 原文视频:https://u.geekbang.org/lesson/535?article681062 Redis最佳实践 普通KEY Redis 的key虽然可以自定义,但是最好遵循下面几个实践的约定: 格式:[业务名称]:[数据名]:[id] 长度不超过44字节 不…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...