手动搭建gateway,项目集成gateway实现Token效果

目录

  • 背景
  • 步骤
    • 1、首先创建springboot项目
    • 2、引入依赖
    • 3、配置文件!!!!!(超级重要!!!根据自己的需要进行配置)
    • 4、相关类
    • 我们在服务中进行的白名单中接口的操作如下
  • 测试
    • 存:
    • 拿:
  • 总结

背景

现在想要进行token校验,故引入gateway服务。
首先阅读官网,知道概念:Gateway官网详解

步骤

1、首先创建springboot项目

看整体的目录结构
在这里插入图片描述

2、引入依赖

 <dependencies><!--gateway的依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos注册与发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--nacos配置中心来做配置管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>com.tfjybj</groupId><artifactId>fewCode-common-redis</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId></dependency></dependencies>

3、配置文件!!!!!(超级重要!!!根据自己的需要进行配置)

server:port: 8088servlet:context-path: /apispring:cloud:gateway:discovery:locator:enabled: trueroutes:- id: login_routeuri: lb://fewCode-provider-login#uri: http://localhost:8001/predicates:- Path=/login/**,/Curriculum/**,/classes/**filters:- RewritePath=/(?<segment>.*),/$\{segment}
leyou:filter:  #需要进行过滤的白名单allowPaths:- /login/checkLogin- /login/user- /login/userLogin- /upload/filetokenExpire: 1440

这份配置是用于Spring Cloud Gateway的配置文件,用于构建API网关。让我来解释一下每个部分的含义:

服务器配置:

服务器监听端口为8088。
Servlet的上下文路径设置为"/api",意味着所有API的端点都将具有这个前缀。
Spring Cloud Gateway配置:

服务发现定位器:启用,这意味着网关将使用服务发现来查找后端服务的路由。在动态的微服务环境中非常有用。
路由:路由配置指定了网关如何将传入的请求路由到后端服务。在这里,定义了一个路由:
id: login_route - 这是该路由的唯一标识符。
uri: lb://fewCode-provider-login - 后端服务的URI,用于处理具有负载均衡器(lb)的请求。服务名为"fewCode-provider-login",网关将使用服务发现来定位该服务。
predicates: 定义了应用此路由的条件。在这里,该路由将用于以"/login/“、”/Curriculum/“或”/classes/"开头的路径的请求。
filters: 对请求应用的过滤器,在将其转发到后端服务之前。在这里,使用了一个RewritePath过滤器,用于删除路径末尾的斜杠。
自定义配置:

leyou:这似乎是一些与"leyou"相关的自定义配置,用于特定的过滤逻辑。
filter:这是一个允许白名单路径的配置。
allowPaths:列出的路径将无需任何额外过滤而被允许。这些路径的请求不会受到任何额外的检查。
tokenExpire:设置令牌过期的时间限制(以分钟为单位),这里设置为1440分钟(24小时)。
总体而言,这份配置将Spring Cloud Gateway配置成将传入的请求路由到名为"fewCode-provider-login"的后端服务,前提是请求路径以"/login/“、”/Curriculum/“或”/classes/"开头。同时,它提供了一个白名单,允许无需任何额外过滤的路径。

4、相关类

package com.tfjybj.gateway.config;import com.tfjybj.gateway.filter.AuthorizeFilter;
import com.tfjybj.gateway.filter.RenewFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic AuthorizeFilter authGatewayFilter() {//配置拦截器参数//order:序号,设置拦截器执行顺序,AuthGatewayFilter为1return new AuthorizeFilter(0);}@Beanpublic RenewFilter renewFilter(){// 续约Tokenreturn new RenewFilter(5);}}
package com.tfjybj.gateway.config;import com.tfjybj.gateway.util.FilterProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** 请求白名单**/
@Component
public class IgnorePath {@Autowiredprivate FilterProperties filterProperties;public boolean isAllowPath(String path) {//遍历白名单for (String allowPath : filterProperties.getAllowPaths()) {//判断是否允许if(path.startsWith(allowPath)){return true;}}return  false;}}
package com.tfjybj.gateway.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;@Configuration
public class LapCorsConfiguration {@Beanpublic CorsWebFilter corsWebFilter(){UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration = new CorsConfiguration();//1、配置跨域corsConfiguration.addAllowedHeader("*");corsConfiguration.addAllowedMethod("*");corsConfiguration.addAllowedOrigin("*");corsConfiguration.setAllowCredentials(true);source.registerCorsConfiguration("/**",corsConfiguration);return new CorsWebFilter(source);}
}
package com.tfjybj.gateway.filter;import com.alibaba.fastjson.JSON;import com.tfjybj.gateway.config.IgnorePath;
import com.tfjybj.gateway.result.ResultMsgEnum;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.HashMap;public class AuthorizeFilter implements GlobalFilter, Ordered {private static final Logger log = LogManager.getLogger();@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate IgnorePath ignorePath;private final int order;public AuthorizeFilter(int order) {this.order = order;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();HttpHeaders headers = request.getHeaders();//获取请求的url路径String path = request.getURI().getPath();boolean flag=ignorePath.isAllowPath(path);if (flag) {log.info("请求在白名单中,metaverse.filter: {}",path);return chain.filter(exchange);} else {//获取token值String authorization = headers.getFirst("Authorization");log.info("Authorization值{}", authorization);authorization = authorization.split("Bearer ")[1];//判断redis中是否有tokenBoolean aBoolean = redisTemplate.hasKey("fewCode:userinfo:" + authorization);if (aBoolean){return chain.filter(exchange);}else {//声明变量ServerHttpResponse response = exchange.getResponse();HashMap map = new HashMap();String resp;DataBuffer bodyDataBuffer;//设置响应头response.setStatusCode(HttpStatus.FORBIDDEN);map.put("code", "403");map.put("message", ResultMsgEnum.AUTH_FAILED.getMsg());resp = JSON.toJSONString(map);bodyDataBuffer = response.bufferFactory().wrap(resp.getBytes());response.getHeaders().add("Content-Type","application/json;charset=UTF-8");return response.writeWith(Mono.just(bodyDataBuffer));}}}@Overridepublic int getOrder() {return this.order;}}
package com.tfjybj.gateway.filter;import com.tfjybj.gateway.config.IgnorePath;
import com.tfjybj.gateway.util.FilterProperties;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.concurrent.TimeUnit;/*** token续约的逻辑**/
public class RenewFilter implements GlobalFilter, Ordered {private static final Logger log = LogManager.getLogger();private final int order;@Autowiredprivate StringRedisTemplate stringRedisTemplate;public RenewFilter(int order) {this.order = order;}@Autowiredprivate IgnorePath ignorePath;@Autowiredprivate FilterProperties filterProperties;@Overridepublic int getOrder() {return this.order;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();HttpHeaders headers = request.getHeaders();//获取请求的url路径String path = request.getURI().getPath();boolean flag=ignorePath.isAllowPath(path);if (flag) {log.info("请求在白名单中,metaverse.filter: {}", path);return chain.filter(exchange);}//token值String authorization = headers.getFirst("Authorization");authorization = authorization.split("Bearer ")[1];log.info("Authorization值{}", authorization);//TOKEN续活//解析TOKEN//根据uuid,延长用户信息String uuid = authorization;String key = "fewCode:userinfo:" + uuid;stringRedisTemplate.expire(key, filterProperties.getTokenExpire(), TimeUnit.MINUTES);return chain.filter(exchange);}}
package com.tfjybj.gateway.result;public enum ResultMsgEnum {FIND_SUCCESS("查询成功!"),FIND_FAIL("查询失败!"),UPDATE_SUCCESS("更新成功"),UPDATE_FAIL("更新失败"),DELETE_SUCCESS("删除成功"),DELETE_FAIL("删除失败"),SEND_SUCCESS("发送成功"),SEND_FAIL("发送失败"),EXECUTE_SUCCESS("执行成功!"),EXECUTE_FAIL("执行失败!"),AUTH_FAILED("权限认证失败"),AUTH_SUCCESS("权限认证成功");private final String msg;ResultMsgEnum(String msg) {this.msg = msg;}public String getMsg() {return msg;}
}
package com.tfjybj.gateway.util;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;import java.util.List;@Component
@RefreshScope
@ConfigurationProperties(prefix = "leyou.filter")
public class FilterProperties {public void setAllowPaths(List<String> allowPaths) {this.allowPaths = allowPaths;}public List<String> getAllowPaths() {return allowPaths;}private List<String> allowPaths;/*** token过期时间*/private Integer tokenExpire;public Integer getTokenExpire() {return tokenExpire;}public void setTokenExpire(Integer tokenExpire) {this.tokenExpire = tokenExpire;}
}
package com.tfjybj.gateway;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
//@EnableDiscoveryClientpublic class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}}

我们在服务中进行的白名单中接口的操作如下

(主要是根据传过来的信息生成token,然后以键值对的形式存入redis中,方便后续通过redis根据token拿人的信息):

RestController
@RequestMapping("/login")
public class LoginController {@Autowiredprivate Actor actorInfo;@ApiOperation("学生登录验证")@RequestMapping(value="checkLogin",method= RequestMethod.POST)@Transactional(rollbackFor = Exception.class)public Actor checkLoginInfo(@RequestBody Actor actor){return actorInfo.notifyStudentCheckLoginInfo(actor);}
}
public Actor notifyStudentCheckLoginInfo(Actor student){Actor actor;for (Actor studentInfo:allStudent){actor=studentInfo.checkLoginInfo(student);if (!ObjectUtils.isEmpty(actor)){//生成UUIDString uuid = CreateUUID.createUUID();//存入redissaveRedis(uuid, actor);//生成token,封装到请求头putHeader(uuid);return actor;}}return null;}
public class CreateUUID {public CreateUUID() {}public static String createUUID() {String preUuid = UUID.randomUUID().toString();String newUUID = preUuid.replace("-", "");return newUUID;}
}
   private void saveRedis(String uuid, Object userInfo) {//拼接key,user信息序列化,存入redis,过期时间在nacos中设置String key = "fewCode:userinfo:" + uuid;String userJson = JSONObject.toJSONString(userInfo);redisTemplate.opsForValue().set(key, userJson);redisTemplate.expire(key, 1440, TimeUnit.MINUTES);}
   private void putHeader(String token) {ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletResponse response = sra.getResponse();response.setHeader("Authorization", token);}

测试

存:

在这里插入图片描述

在这里插入图片描述
将断点打到这里,可以观察到我们要请求的服务IP+端口号还有url地址,如下
相当手动访问

在这里插入图片描述

调通后存入redis中如下

在这里插入图片描述

拿:

然后拿着根据token获取信息

在这里插入图片描述

在这里插入图片描述

package com.tfjybj.login.service.impl;import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;@Service
public class AnalysisTokenService {@Autowiredprivate StringRedisTemplate redisTemplate;/*** 获取当前登陆人id** @return*/public String getUserId() {JSONObject userData = getUserData();return userData.get("id").toString();}/*** 获取用户code** @return*/public String getUserAccount() {JSONObject userData = getUserData();return userData.get("account").toString();}/*** 获取当前登陆人name** @return*/public String getUserName() {JSONObject userData = getUserData();return userData.get("name").toString();}public JSONObject getUserData() {//从请求头获取tokenServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();String token = sra.getRequest().getHeader("Authorization");token = token.split("Bearer ")[1];//解析tokenJSONObject userJson = this.analysisToken(token);return userJson;}public JSONObject analysisToken  (String token){//解析tokenString key= "fewCode:userinfo:"+token;String userInfoStr = redisTemplate.opsForValue().get(key);JSONObject userJson = JSONObject.parseObject(userInfoStr);
//        String data = jsonObject.get("data").toString();
//        JSONObject userJson = JSONObject.parseObject(data);return userJson;}}

总结

1、搞懂gateway是干嘛的
2、知道配置文件中各个参数是什么

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/11883.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信驰达推出RTL8720DN系列2.4G和5G双频Wi-Fi+蓝牙二合一模块

近日&#xff0c;领先的无线物联网通信模块厂商深圳信驰达科技RF-star推出了基于RTL8720DN SoC的2.4 GHz和5 GHz双频Wi-Fi蓝牙二合一模块—RF-WM-20DNB1。 图 1信驰达RF-WM-20DNB1 Wi-Fi模块 RF-WM-20DNB1是一款低功耗单芯片无线蓝牙和Wi-Fi组合模块&#xff0c;支持双频(2.4 G…

详细介绍如何使用HuggingFace和PyTorch进行医学图像分割-附源码

医学图像分割是一种创新过程,使外科医生能够拥有虚拟的“X 射线视觉”。它是医疗保健领域非常有价值的工具,可提供非侵入性诊断和深入分析。考虑到这一点,在这篇文章中,我们将探索威斯康辛大学麦迪逊分校胃肠道图像分割Kaggle 挑战数据集。作为该项目的一部分,我们将使用 …

爬虫005_python类型转换_其他类型转换为整型_转换为Float类型_转换为字符串_转换为布尔值---python工作笔记023

首先来看,字符串转换成int 很简单 float转换成int 会把小数点后面的内容丢掉 boolean转换为int true是1 false 是0 然后字符串转换为int,要注意 不能有特殊字符比如1.23 中有点 就报错 上面字符串12ab,有ab也报错 看上面

Docker可视化管理工具Portainer多机器安装使用

一、首先得安装docker Docker安装并指定主目录:https://blog.csdn.net/wdy_2099/article/details/77367107 二、使用docker方式安装portainer 安装命令如下&#xff1a; docker run -it -d \-p 8999:9000 \--name portainer \--restart always \-v /var/run/docker.sock:/v…

Linux Ubuntu crontab 添加错误 提示:no crontab for root - using an empty one 888

资料 错误提示&#xff1a; no crontab for root - using an empty one 888 原因剖析&#xff1a; 第一次使用crontab -e 命令时会让我们选择编辑器&#xff0c;很多人会不小心选择默认的nano&#xff08;不好用&#xff09;&#xff0c;或则提示no crontab for root - usin…

【图像分类】CNN + Transformer 结合系列.1

介绍三篇结合使用CNNTransformer进行学习的论文&#xff1a;CvT&#xff08;ICCV2021&#xff09;&#xff0c;Mobile-Former&#xff08;CVPR2022&#xff09;&#xff0c;SegNetr&#xff08;arXiv2307&#xff09;. CvT: Introducing Convolutions to Vision Transformers, …

Windows bat 查找文件被哪个进程占用,并终止该进程

一、背景 我有个批处理脚本如下&#xff1a; echo off chcp 936 & cls cd /D F:\Chen\python3\ExciseC set fdate%date:~0,4%%date:~5,2%%date:~8,2% python main.py >> crawl_record_%fdate%.log 2>&1 for /F %%f in (dir crawl_record_*.log /B ^| find /…

机器学习——异常检测

异常点检测(Outlier detection)&#xff0c;⼜称为离群点检测&#xff0c;是找出与预期对象的⾏为差异较⼤的对象的⼀个检测过程。这些被检测出的对象被称为异常点或者离群点。异常点&#xff08;outlier&#xff09;是⼀个数据对象&#xff0c;它明显不同于其他的数据对象。异…

Linux工具【1】(编辑器vim、编译器gcc与g++)

vim详解 引言vimVim的三种模式及模式切换普通模式下操作底行模式下操作 gcc与ggcc的使用&#xff08;g类似&#xff09;预编译编译汇编链接静态库与动态库 总结 引言 vim&#xff08;vi improved&#xff09;编辑器是从 vi 发展出来的一个文本编辑器。 代码补全、编译及错误跳…

opencv python 训练自己的分类器

源码下载 一、分类器制作 1.样本准备 收集好你所需的正样本&#xff0c;和负样本&#xff0c;分别保存在不同文件夹 在pycharm新建项目&#xff0c;项目结构如下&#xff1a;has_mask文件夹放置正样本&#xff0c;no_mask文件夹放置负样本 安装opencv&#xff0c;把opencv包…

Day.4 刷题练习(自守数)

题目&#xff1a; 例子&#xff1a; 分析题目&#xff1a; 主要目的&#xff1a;给定一个范围小于等于N&#xff0c;在这个范围中找自守数&#xff08;自身等于平方后的尾部数据如5&#xff1a;5 ^ 2 25 &#xff0c; 然后 5 与 平方的后的尾部相等&#xff09; 思路&#x…

ancos注册中心、网关和静态化freemarker、对象存储服务MinIO

1、docker安装ancos ①&#xff1a;docker拉取镜像 docker pull nacos/nacos-server:1.2.0②&#xff1a;创建容器 docker run --env MODEstandalone --name nacos --restartalways -d -p 8848:8848 nacos/nacos-server:1.2.0③&#xff1a;访问地址&#xff1a;http://192…

Qt : day4

1.思维导图 2.服务器 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化空间server new QTcpServer(this);}Widget::~Widget() {delete ui;…

下级平台级联视频汇聚融合平台EasyCVR,层级显示不正确的原因排查

视频汇聚平台安防监控EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RTMP、FLV、HLS、WebRTC等…

【计算机网络】第 3 课 - 计算机网络体系结构

欢迎来到博主 Apeiron 的博客&#xff0c;祝您旅程愉快 &#xff01; 时止则止&#xff0c;时行则行。动静不失其时&#xff0c;其道光明。 目录 1、常见的计算机网络体系结构 2、计算机网络体系结构分层的必要性 2.1、物理层 2.2、数据链路层 2.3、网路层 2.4、运输层 2…

Sentinel nacos spring cloud 持久化配置---分布式/微服务流量控制

文章目录 sentinel控制台安装目标实现代码地址版本说明maven spring-cloud-starter-alibaba-sentinel依赖yml文件Nacos业务规则配置看源码配置规则SentinelProperties 总配置加载DataSourcePropertiesConfiguration 配置标准的nacos配置注册具体sentinel配置 外传 sentinel控制…

Chrome 115 有哪些值得关注的新特性?

今天带大家一起来了解一下 Chrome 115 值得关注的新特性。 滚动动画 用滚动驱动的动画是网站上非常常见的用户体验模式&#xff0c;比如当页面向前或向后滚动时&#xff0c;对应的动画也会向前或向后移动。 比如下面图中这种比较常见的&#xff0c;页面顶部的进度条随着滚动…

华为OD机试真题 Java 实现【数字涂色】【2022Q4 100分】,附详细解题思路

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#xff09;》。 刷的越多&…

Flowable-UI

title: Flowable-UI date: 2023-7-23 12:19:20 tags: - Flowable Flowable-UI 安装 手把手教大家画了这样一个流程图&#xff0c;虽然说它不是特别好用&#xff0c;但是也不是不能用&#xff0c;也能用。好了&#xff0c;那么接下来的话&#xff0c;我们这个就先告一个段落&…

客户方数据库服务器CPU负载高优化案例

客户方数据库服务器CPU负载高优化案例 背景 上周线上服务出现一个问题&#xff0c;打开某个页面&#xff0c;会导致其它接口请求响应超时&#xff0c;排查后发现数据库响应超400s&#xff0c;之前1s就可查到数据。 具体原因是有个大屏统计页面&#xff0c;会实时查看各业务服…