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字节 不…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
