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

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校验

思路分析:

  1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录

  2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户

  3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN

  4. 网关过滤器解析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集成方法以及拦截器和过滤器的使用

前提&#xff1a;请先创建好一个SpringBoot项目 1. 引入依赖 SpringCloud 和 alibabaCloud 、 SpringBoot间对版本有强制要求&#xff0c;我使用的springboot是3.0.2的版本。版本对应关系请看&#xff1a;版本说明 alibaba/spring-cloud-alibaba Wiki GitHub <dependency…...

第G2周:人脸图像生成(DCGAN)

&#x1f368; 本文为[&#x1f517;365天深度学习训练营学习记录博客\n&#x1f366; 参考文章&#xff1a;365天深度学习训练营\n&#x1f356; 原作者&#xff1a;[K同学啊 | 接辅导、项目定制]\n&#x1f680; 文章来源&#xff1a;[K同学的学习圈子](https://www.yuque.co…...

【Web】Ctfshow Thinkphp5 非强制路由RCE漏洞

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

python3遇到Can‘t connect to HTTPS URL because the SSL module is not available.

远程服务器centos7系统上有minicoda3&#xff0c;觉得太占空间&#xff0c;就把整个文件夹删了&#xff0c;原先的Python3也没了&#xff0c;都要重装。 我自己的步骤&#xff1a;进入管理员模式 1.下载Python3的源码&#xff1a; wget https://www.python.org/ftp/python/3.1…...

QSPI Flash xip取指同时program过程中概率性出现usb播歌时断音

项目场景&#xff1a; USB Audio芯片&#xff0c;代码放到qspi flash中&#xff0c;执行代码时&#xff0c;客户会偶尔保存一些参数&#xff0c;即FPGA验证过程中&#xff0c;每隔10ms向flash info区烧写4个byte&#xff08;取指过程一直存在&#xff0c;且时隙软件不可控&…...

MySQL聚簇索引和非聚簇索引的区别

前言: 聚簇索引和非聚簇索引是数据库中的两种索引类型&#xff0c;他们在组织和存储数据时有不同的方式。 聚簇索引&#xff1a; 简单理解&#xff0c;就是将数据和索引放在了一起&#xff0c;找到了索引也就找到了数据。对于聚簇索引来说&#xff0c;他的非叶子节点上存储的是…...

【C#】蜗牛爬井问题C#控制台实现

文章目录 一、问题描述二、C#控制台代码 一、问题描述 井深30米&#xff0c;蜗牛在井底&#xff0c;每天爬3米又滑下1米&#xff0c;问第几天爬出来 二、C#控制台代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System…...

IP地址的四大类型:动态IP、固定IP、实体IP、虚拟IP的区别与应用

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

Linux Debian12安装和使用ImageMagick图像处理工具 常见图片png、jpg格式转webp格式

一、ImageMagick简介 ImageMagick是一套功能强大、稳定而且免费的工具集和开发包。可以用来读、写和图像格式转换&#xff0c;可以处理超过100种图像格式&#xff0c;包括流行的TIFF, JPEG, GIF, PNG, PDF以及PhotoCD等格式。对图片的操作&#xff0c;即可以通过命令行进行&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系列——正则表达式

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

命令行创建Vue项目

Vue项目创建 1. 打开UI界面 在命令行中&#xff0c;执行如下指令&#xff1a; vue ui 2. 打开项目管理器 3. 创建项目 创建项目的过程&#xff0c;需要联网进行&#xff0c;这可能会耗时比较长的时间&#xff0c;请耐心等待。 windows的命令行&#xff0c;容易卡顿&#xff0c…...

01.PostgreSQL基本SELECT语句

1. SQL简介 SQL 是用于访问和处理数据库的标准的计算机语言。 SQL有两个标准:分别是SQL92和SQL99,他们分别代表了92年和99年颁布的SQL标准,我们今天使用的SQL语言依然遵循这些标准。 注意:除了 SQL 标准之外,大部分 SQL 数据库程序都拥有它们自己的私有扩展! 2. SQL分…...

UDP信号多个电脑的信息传输测试、配置指南

最近要做一个东西&#xff0c;关于一个软件上得到的信号&#xff0c;如何通过连接的局域网&#xff0c;将数据传输出去。我没做过相关的东西&#xff0c;但是我想应该和软件连接数据库的过程大致是差不多的&#xff0c;就一个ip和一个端口号啥的。 一.问题思路 多个设备同时连…...

先序+中序还原二叉树【数据结构】

先序中序还原二叉树 题目描述 给定一棵二叉树的先序遍历序列和中序遍历序列&#xff0c;要求计算该二叉树的高度。 输入 输入首先给出正整数N&#xff08;≤50&#xff09;&#xff0c;为树中结点总数。下面两行先后给出先序和中序遍历序列&#xff0c;均是长度为N的不包含重…...

【全网首发】洛谷P2678 [NOIP2015 提高组] 跳石头

Everyday English You don’t become what you want; you become whatyou believe. —Oprah Winfrey 你不是成为你想要的&#xff0c;你成为你所相信的。 洛谷P2678 [NOIP2015 提高组] 跳石头 题目描述 一年一度的“跳石头”比赛又要开始了&#xff01; 这项比赛将在一条笔…...

Gpt指引ubuntu安装java8/11

在Ubuntu系统上安装Java环境通常包括以下几个步骤&#xff1a; 更新软件包索引&#xff1a; 在安装新软件之前&#xff0c;最好先更新Ubuntu的软件包索引。这可以确保你安装的是最新版本的软件包。可以使用以下命令来更新&#xff1a; sudo apt update安装Java&#xff1a; U…...

【MCAL】TC397+EB-tresos之MCU配置实战 - 芯片时钟

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

最新AI系统ChatGPT网站H5系统源码,支持AI绘画,GPT语音对话+ChatFile文档对话总结+DALL-E3文生图

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Ch…...

如何在MAC OS中的XCODE下添加 <bits/stdc++.h>

mac上使用的编译器是Clang&#xff0c;但是没有万能头文件bits/stdc.h\&#xff0c;本文介绍如何添加万能头文件 Xcode 版本&#xff1a;15.1 - 打开应用程序-Xcode-右键显示包内容 Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/includ…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

2021-03-15 iview一些问题

1.iview 在使用tree组件时&#xff0c;发现没有set类的方法&#xff0c;只有get&#xff0c;那么要改变tree值&#xff0c;只能遍历treeData&#xff0c;递归修改treeData的checked&#xff0c;发现无法更改&#xff0c;原因在于check模式下&#xff0c;子元素的勾选状态跟父节…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

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;用于图像分割或平滑处理。 该函数将输入图像中的…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...