Gateway集成方法以及拦截器和过滤器的使用
前提:请先创建好一个SpringBoot项目
1. 引入依赖
SpringCloud 和 alibabaCloud 、 SpringBoot间对版本有强制要求,我使用的springboot是3.0.2的版本。版本对应关系请看:版本说明 · alibaba/spring-cloud-alibaba Wiki · GitHub
<dependencyManagement><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>2022.0.3</version></dependency></dependencyManagement><dependencies><!-- SpringCloud组件之一,不加会提示错误 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-loadbalancer</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId><version>3.1.4</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency></dependencies>
2. 搭建网关
配置bootstrap.yml文件:
server:port: 8083
spring:application:name: big-news-admin-gatewaycloud:nacos:discovery:server-addr: 你的ip:8848config:server-addr: 你的ip:8848file-extension: yml
Nacos配置中心:
yml示例:
spring:data:redis:host: localhostport: 6379cloud:gateway:globalcors:add-to-simple-url-handler-mapping: truecorsConfigurations:'[/**]':allowedHeaders: "*"allowedOrigins: "*"allowedMethods:- GET- POST- DELETE- PUT- OPTIONroutes:# 平台管理- id: useruri: lb://big-news-userpredicates:- Path=/user/**# 分类- id: categoryuri: lb://big-news-categorypredicates:- Path=/category/**# 文章- id: articleuri: lb://big-news-articlepredicates:- Path=/article/**# 文件- id: commonuri: lb://big-news-commonpredicates:- Path=/upload/**
token:secretKey: rikka7e7f74ef-62b5-4b29-96ae-c698f7c823c1expirationTime: 1080000060
解释:
该配置用于解决跨域问题
路由断言规则,id需唯一,uri中的名称需要对应服务的应用名。path用于匹配路由。
以下图举例:uri意味着将请求匹配到nacos中名叫big-news-user的服务,path意味着根据只要请求携带`user`就匹配服务。
可用 filters 过滤掉请求中的字段,比如下图。意味着最后到服务的实际请求不会携带`user`,你就不需要在controller的接收路径上上写`user`。
3. 全局过滤器实现jwt校验
思路分析:
用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录
用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户
用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN
网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误
3.1 拷贝一份jwt工具类到网关服务
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;@Component
public class JwtUtil {private static final String USER_CLAIMS_KEY = "user";// 过期时间@Value("${token.expirationTime}")private long EXPIRE_TIME;// 密钥@Value("${token.secretKey}")private String SECRET;/*** 创建JWT Token** @param payload 载荷(Claims)* @return JWT Token*/public String createToken(Map<String, Object> payload) {// 1. 创建一个密钥SecretKey key = Keys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8));// 2. 创建JWT Builder// 注意:这里的签名算法不能是 RS256,需要使用 HS256io.jsonwebtoken.JwtBuilder builder = Jwts.builder().setClaims(payload).setExpiration(new Date(System.currentTimeMillis() + EXPIRE_TIME)).signWith(key, SignatureAlgorithm.HS256);// 3. 生成JWT Tokenreturn builder.compact();}/*** 解析JWT Token** @param token JWT Token* @return 载荷(Claims)*/public Map<String, Object> parseToken(String token) {// 1. 获取密钥SecretKey key = Keys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8));// 2. 解析JWT TokenClaims claims = Jwts.parser().setSigningKey(key).build().parseClaimsJws(token).getBody();// 3. 将Claims里的内容转换成MapMap<String, Object> payload = new HashMap<>(claims);payload.remove("exp");payload.remove("iat");payload.remove("iss");payload.remove("aud");payload.remove("nbf");payload.remove("sub");payload.remove("jti");return payload;}/*** 获取JWT Token的过期时间** @param token JWT Token* @return 过期时间*/public Date getExpirationDateFromToken(String token) {Claims claims = parseClaims(token);if (claims != null) {return claims.getExpiration();}return null;}/*** 验证JWT Token是否有效** @param token JWT Token* @return 是否有效*/public boolean validateToken(String token) {try {parseClaims(token);return true;} catch (Exception e) {return false;}}/*** 获取payload中的用户信息** @param token JWT Token* @return 用户信息*/public Map<String, Object> getUserFromToken(String token) {Map<String, Object> user = null;Claims claims = parseClaims(token);if (claims != null) {user = (Map<String, Object>) claims.get(USER_CLAIMS_KEY);}return user;}/*** 解析JWT Token中的Claims** @param token JWT Token* @return Claims*/public Claims parseClaims(String token) {try {SecretKey key = Keys.hmacShaKeyFor(SECRET.getBytes(StandardCharsets.UTF_8));return Jwts.parser().setSigningKey(key).build().parseClaimsJws(token).getBody();} catch (Exception e) {return null;}}}
3.2 网关微服务中新建全局过滤器
import cn.hutool.json.JSONUtil;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.xin.common.properties.TokenProperties;
import com.xin.common.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
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;import java.util.Objects;@Component
public class AuthorizeFilter implements Ordered, GlobalFilter {@Autowiredprivate StringRedisTemplate stringRedisTemplate;//用于接收token的信息,你可按实际请看书写,也可以直接在这个类里定义静态参数。//tokenProperties主要包含:密钥key、过期时间@Autowiredprivate TokenProperties tokenProperties;@Autowiredprivate JwtUtil jwtUtil;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1.获取请求ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();//2.判断是否是登录操作if (request.getURI().getPath().contains("/login")) {//放行return chain.filter(exchange);}String token = request.getHeaders().getFirst("Authorization");//3.若token为空,校验失败if (StringUtils.isEmpty(token)){response.setStatusCode(HttpStatus.UNAUTHORIZED);//结束请求return response.setComplete();}try {//4. 解析tokenClaims claims = jwtUtil.parseClaims(token);//获得token解析后中的用户信息Object o = claims.get("user");String user = JSONUtil.toJsonStr(o);String id = user.substring(user.indexOf(":")+1, user.indexOf(","));//5.判断token是否在redis中过期,或删除String object = stringRedisTemplate.opsForValue().get("token:" + id + ":" + token);if (Objects.isNull(object)) {response.setStatusCode(HttpStatus.UNAUTHORIZED);//结束请求return response.setComplete();}// 将用户信息存放进 header中ServerHttpRequest serverHttpRequest = request.mutate().headers(httpHeaders -> {httpHeaders.add("user", user + "");}).build();exchange.mutate().request(serverHttpRequest).build();}catch (Exception e){e.printStackTrace();response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}//5.放行return chain.filter(exchange);}/*** 优先级设置,值越小 优先级越高* @return*/@Overridepublic int getOrder() {return 0;}
}
注意,该过滤器只是实现了对Token的校验,并将解析结果存放进header进一步转发。获取user信息,还需在实际的服务里定义拦截器获取:
@Component @Slf4j public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String userString = request.getHeader("user");Optional<String> optional = Optional.ofNullable(userString);if(optional.isPresent()) {//把用户存入threadLocal中TreadLocalUtil.setUser(userString);log.info("设置用户信息到threadlocal中...");}return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {TreadLocalUtil.clear();log.info("清理threadlocal...");} }
在WebMvcConfig中配置该拦截器:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configuration public class WebMvcConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");} }
最后最后!!!各位看官觉得有用就收藏、点赞、评论一下吧。我看到问题后,我会第一时间回复的!
相关文章:

Gateway集成方法以及拦截器和过滤器的使用
前提:请先创建好一个SpringBoot项目 1. 引入依赖 SpringCloud 和 alibabaCloud 、 SpringBoot间对版本有强制要求,我使用的springboot是3.0.2的版本。版本对应关系请看:版本说明 alibaba/spring-cloud-alibaba Wiki GitHub <dependency…...

第G2周:人脸图像生成(DCGAN)
🍨 本文为[🔗365天深度学习训练营学习记录博客\n🍦 参考文章:365天深度学习训练营\n🍖 原作者:[K同学啊 | 接辅导、项目定制]\n🚀 文章来源:[K同学的学习圈子](https://www.yuque.co…...

【Web】Ctfshow Thinkphp5 非强制路由RCE漏洞
目录 非强制路由RCE漏洞 web579 web604 web605 web606 web607-610 前面审了一些tp3的sql注入,终于到tp5了,要说tp5那最经典的还得是rce 下面介绍非强制路由RCE漏洞 非强制路由RCE漏洞原理 非强制路由相当于开了一个大口子,可以任意调用当前框…...

python3遇到Can‘t connect to HTTPS URL because the SSL module is not available.
远程服务器centos7系统上有minicoda3,觉得太占空间,就把整个文件夹删了,原先的Python3也没了,都要重装。 我自己的步骤:进入管理员模式 1.下载Python3的源码: wget https://www.python.org/ftp/python/3.1…...
QSPI Flash xip取指同时program过程中概率性出现usb播歌时断音
项目场景: USB Audio芯片,代码放到qspi flash中,执行代码时,客户会偶尔保存一些参数,即FPGA验证过程中,每隔10ms向flash info区烧写4个byte(取指过程一直存在,且时隙软件不可控&…...
MySQL聚簇索引和非聚簇索引的区别
前言: 聚簇索引和非聚簇索引是数据库中的两种索引类型,他们在组织和存储数据时有不同的方式。 聚簇索引: 简单理解,就是将数据和索引放在了一起,找到了索引也就找到了数据。对于聚簇索引来说,他的非叶子节点上存储的是…...
【C#】蜗牛爬井问题C#控制台实现
文章目录 一、问题描述二、C#控制台代码 一、问题描述 井深30米,蜗牛在井底,每天爬3米又滑下1米,问第几天爬出来 二、C#控制台代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System…...

IP地址的四大类型:动态IP、固定IP、实体IP、虚拟IP的区别与应用
在网络通信中,IP地址是设备在互联网上唯一标识的关键元素。动态IP、固定IP、实体IP和虚拟IP是四种不同类型的IP地址,它们各自具有独特的特点和应用场景。 1. 动态IP地址: 动态IP地址是由Internet Service Provider(ISPÿ…...

Linux Debian12安装和使用ImageMagick图像处理工具 常见图片png、jpg格式转webp格式
一、ImageMagick简介 ImageMagick是一套功能强大、稳定而且免费的工具集和开发包。可以用来读、写和图像格式转换,可以处理超过100种图像格式,包括流行的TIFF, JPEG, GIF, PNG, PDF以及PhotoCD等格式。对图片的操作,即可以通过命令行进行&am…...
JavaScript二
目录 流程控制 if判断 while循环 do while for循环 forEach for in Map与set iterator 流程控制 if判断 <script>use strictvar age 5;if(age < 3){alert("haha");}else if(age < 5){alert("hi world");}else{alert("hello wor…...

JavaScript系列——正则表达式
文章目录 需求场景正则表达式的定义创建正则表达式通过 / 表示式/ 创建通过构造函数创建 编写一个正则表达式的模式使用简单模式使用特殊字符常用特殊字符列表特殊字符组和范围 正则表达式使用代码演示 常用示例验证手机号码合法性 小结 需求场景 在前端开发领域,在…...

命令行创建Vue项目
Vue项目创建 1. 打开UI界面 在命令行中,执行如下指令: vue ui 2. 打开项目管理器 3. 创建项目 创建项目的过程,需要联网进行,这可能会耗时比较长的时间,请耐心等待。 windows的命令行,容易卡顿,…...
01.PostgreSQL基本SELECT语句
1. SQL简介 SQL 是用于访问和处理数据库的标准的计算机语言。 SQL有两个标准:分别是SQL92和SQL99,他们分别代表了92年和99年颁布的SQL标准,我们今天使用的SQL语言依然遵循这些标准。 注意:除了 SQL 标准之外,大部分 SQL 数据库程序都拥有它们自己的私有扩展! 2. SQL分…...

UDP信号多个电脑的信息传输测试、配置指南
最近要做一个东西,关于一个软件上得到的信号,如何通过连接的局域网,将数据传输出去。我没做过相关的东西,但是我想应该和软件连接数据库的过程大致是差不多的,就一个ip和一个端口号啥的。 一.问题思路 多个设备同时连…...
先序+中序还原二叉树【数据结构】
先序中序还原二叉树 题目描述 给定一棵二叉树的先序遍历序列和中序遍历序列,要求计算该二叉树的高度。 输入 输入首先给出正整数N(≤50),为树中结点总数。下面两行先后给出先序和中序遍历序列,均是长度为N的不包含重…...
【全网首发】洛谷P2678 [NOIP2015 提高组] 跳石头
Everyday English You don’t become what you want; you become whatyou believe. —Oprah Winfrey 你不是成为你想要的,你成为你所相信的。 洛谷P2678 [NOIP2015 提高组] 跳石头 题目描述 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔…...
Gpt指引ubuntu安装java8/11
在Ubuntu系统上安装Java环境通常包括以下几个步骤: 更新软件包索引: 在安装新软件之前,最好先更新Ubuntu的软件包索引。这可以确保你安装的是最新版本的软件包。可以使用以下命令来更新: sudo apt update安装Java: U…...

【MCAL】TC397+EB-tresos之MCU配置实战 - 芯片时钟
本篇文章介绍了在TC397平台使用EB-treso对MCU驱动模块进行配置的实战过程,主要介绍了后续基本每个外设模块都要涉及的芯片时钟部分,帮助读者了解TC397芯片的时钟树结构,在后续计算配置不同外设模块诸如通信速率,定时器周期等&…...

最新AI系统ChatGPT网站H5系统源码,支持AI绘画,GPT语音对话+ChatFile文档对话总结+DALL-E3文生图
一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Ch…...

如何在MAC OS中的XCODE下添加 <bits/stdc++.h>
mac上使用的编译器是Clang,但是没有万能头文件bits/stdc.h\,本文介绍如何添加万能头文件 Xcode 版本:15.1 - 打开应用程序-Xcode-右键显示包内容 Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/includ…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力
引言: 在人工智能快速发展的浪潮中,快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型(LLM)。该模型代表着该领域的重大突破,通过独特方式融合思考与非思考…...