网关路由登录校验

网关过滤器

登录校验必须在请求转发到微服务之前做,否则就失去了意义。而网关的请求转发是Gateway内部代码实现的,要想在请求转发之前做登录校验,就必须了解Gateway内部工作的基本原理。

暂时无法在飞书文档外展示此内容

如图所示:

  1. 客户端请求进入网关后由HandlerMapping对请求做判断,找到与当前请求匹配的路由规则(Route),然后将请求交给WebHandler去处理。

  2. WebHandler则会加载当前路由下需要执行的过滤器链(Filter chain),然后按照顺序逐一执行过滤器(后面称为Filter)。

  3. 图中Filter被虚线分为左右两部分,是因为Filter内部的逻辑分为prepost两部分,分别会在请求路由到微服务之前之后被执行。

  4. 只有所有Filterpre逻辑都依次顺序执行通过后,请求才会被路由到微服务。

  5. 微服务返回结果后,再倒序执行Filterpost逻辑。

  6. 最终把响应结果返回。

如图中所示,最终请求转发是有一个名为NettyRoutingFilter的过滤器来执行的,而且这个过滤器是整个过滤器链中顺序最靠后的一个。如果我们能够定义一个过滤器,在其中实现登录校验逻辑,并且将过滤器执行顺序定义到NettyRoutingFilter之前

简而言之,网关里有很多自带的过滤器,我们需要自定义一个,并且得在NettyRoutingFilter之前。

登录校验

1、创建一个网关服务hm-geteway,引入依赖

       <!--网关--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos discovery--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--负载均衡--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>

2、配置路由

接下来,在hm-gateway模块的resources目录新建一个application.yaml文件,内容如下:

server:port: 8080
spring:application:name: gatewaycloud:nacos:server-addr: 192.168.64.100:8848  #你自己的虚拟机gateway:routes:- id: item # 路由规则id,自定义,唯一uri: lb://item-service # 路由的目标服务,lb代表负载均衡,会从注册中心拉取服务列表predicates: # 路由断言,判断当前请求是否符合当前规则,符合则路由到目标服务- Path=/items/**,/search/** # 这里是以请求路径作为判断规则- id: cart # uri: lb://cart-service # predicates: # - Path=/carts/** # - id: user # uri: lb://user-service # predicates: # - Path=/users/** # 

3、导入JWT

具体作用如下:

AuthProperties:配置登录校验需要拦截的路径,因为不是所有的路径都需要登录才能访问

JwtProperties:定义与JWT工具有关的属性,比如秘钥文件位置

SecurityConfig:工具的自动装配

JwtTool:JWT工具,其中包含了校验和解析token的功能

hmall.jks:秘钥文件

package com.heima.conf;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;import java.util.List;@Data
@ConfigurationProperties(prefix = "hm.auth")
public class AuthProperties {private List<String> includePaths;private List<String> excludePaths;
}
package com.heima.conf;import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;import java.time.Duration;@Data
@ConfigurationProperties(prefix = "hm.jwt")
public class JwtProperties {private Resource location;private String password;private String alias;private Duration tokenTTL = Duration.ofMinutes(10);
}
package com.heima.conf;import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;import java.security.KeyPair;@Configuration
@EnableConfigurationProperties(JwtProperties.class)
public class SecurityConfig {@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Beanpublic KeyPair keyPair(JwtProperties properties){// 获取秘钥工厂KeyStoreKeyFactory keyStoreKeyFactory =new KeyStoreKeyFactory(properties.getLocation(),properties.getPassword().toCharArray());//读取钥匙对return keyStoreKeyFactory.getKeyPair(properties.getAlias(),properties.getPassword().toCharArray());}
}
package com.heima.utils;import cn.hutool.core.exceptions.ValidateException;
import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTValidator;
import cn.hutool.jwt.signers.JWTSigner;
import cn.hutool.jwt.signers.JWTSignerUtil;
import com.hmall.common.exception.UnauthorizedException;
import org.springframework.stereotype.Component;import java.security.KeyPair;
import java.time.Duration;
import java.util.Date;@Component
public class JwtTool {private final JWTSigner jwtSigner;public JwtTool(KeyPair keyPair) {this.jwtSigner = JWTSignerUtil.createSigner("rs256", keyPair);}/*** 创建 access-token** @param userDTO 用户信息* @return access-token*/public String createToken(Long userId, Duration ttl) {// 1.生成jwsreturn JWT.create().setPayload("user", userId).setExpiresAt(new Date(System.currentTimeMillis() + ttl.toMillis())).setSigner(jwtSigner).sign();}/*** 解析token** @param token token* @return 解析刷新token得到的用户信息*/public Long parseToken(String token) {// 1.校验token是否为空if (token == null) {throw new UnauthorizedException("未登录");}// 2.校验并解析jwtJWT jwt;try {jwt = JWT.of(token).setSigner(jwtSigner);} catch (Exception e) {throw new UnauthorizedException("无效的token", e);}// 2.校验jwt是否有效if (!jwt.verify()) {// 验证失败throw new UnauthorizedException("无效的token");}// 3.校验是否过期try {JWTValidator.of(jwt).validateDate();} catch (ValidateException e) {throw new UnauthorizedException("token已经过期");}// 4.数据格式校验Object userPayload = jwt.getPayload("user");if (userPayload == null) {// 数据为空throw new UnauthorizedException("无效的token");}// 5.数据解析try {return Long.valueOf(userPayload.toString());} catch (RuntimeException e) {// 数据格式有误throw new UnauthorizedException("无效的token");}}
}

4、编写过滤器

package com.heima.filter;import com.heima.conf.AuthProperties;
import com.heima.utils.JwtTool;
import com.hmall.common.exception.UnauthorizedException;
import com.hmall.common.utils.CollUtils;import lombok.RequiredArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.List;@Component
@RequiredArgsConstructor
@EnableConfigurationProperties(AuthProperties.class)
public class AuthGlobalFilter implements GlobalFilter, Ordered {private final JwtTool jwtTool;private final AuthProperties authProperties;private final AntPathMatcher antPathMatcher = new AntPathMatcher();@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1.获取RequestServerHttpRequest request = exchange.getRequest();// 2.判断是否不需要拦截if(isExclude(request.getPath().toString())){// 无需拦截,直接放行return chain.filter(exchange);}// 3.获取请求头中的tokenString token = null;List<String> headers = request.getHeaders().get("authorization");if (!CollUtils.isEmpty(headers)) {token = headers.get(0);}// 4.校验并解析tokenLong userId = null;try {userId = jwtTool.parseToken(token);} catch (UnauthorizedException e) {// 如果无效,拦截ServerHttpResponse response = exchange.getResponse();response.setRawStatusCode(401);return response.setComplete();}// TODO 5.如果有效,传递用户信息System.out.println("userId = " + userId);// 6.放行return chain.filter(exchange);}private boolean isExclude(String antPath) {for (String pathPattern : authProperties.getExcludePaths()) {if(antPathMatcher.match(pathPattern, antPath)){return true;}}return false;}@Overridepublic int getOrder() { // 过滤器执行顺序,值越小,优先级越高return 0;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

一、Python(介绍、环境搭建)

一、介绍 Python 是一种高级编程语言&#xff0c;具有简洁易读的语法、丰富的库和强大的功能。Python是解释型语言&#xff0c;运行代码必须依赖安装好的解释器。Python目前存在两个版本&#xff1a;Python2、Python3&#xff08;主流使用&#xff09; 二、环境搭建 1.安装P…

四、函数顶层变量

函数&顶层变量 函数定义创建和使用 顶层变量递归函数实用库函数高阶函数与lambda表达式函数类型变量类型别名匿名函数lambda表达式基本用法lambda的简写 内联函数 函数 定义 其实函数我们在一开始就在使用了&#xff1a; fun main() {println("Hello World") …

Python 语言学习——应用1.1 数字图像处理(第一节,颜色)

目录 1.基础知识 2.实战演示 1.基础知识&#xff1a; 1.图像的表示. 函数表示&#xff1a;图像是二维信号&#xff0c;定义为二维函数f(x,y)&#xff0c;其中&#xff0c;x、y是空间坐标&#xff0c;f(x,y)是点(x,y)的幅值。拓展看&#xff0c;视频&#xff0c;又称动态图像…

一阶差分模板的频率响应

一阶差分模板不同于二阶差分模板&#xff0c;它是一个奇对称的模板&#xff0c;傅里叶变换是纯虚数&#xff0c;无法用图形直接显示傅里叶变换&#xff0c;只能显示幅值谱。 冈萨雷斯的这个图我一直很好奇是怎么显示的&#xff0c;也没有坐标轴标出变量表示。 如今终于想明白…

论文笔记:微表情欺骗检测

整理了AAAI2018 Deception Detection in Videos 论文的阅读笔记 背景模型实验可视化 背景 欺骗在我们的日常生活中很常见。一些谎言是无害的&#xff0c;而另一些谎言可能会产生严重的后果。例如&#xff0c;在法庭上撒谎可能会影响司法公正&#xff0c;让有罪的被告逍遥法外。…

04-SpringBootWeb案例(中)

3. 员工管理 完成了部门管理的功能开发之后&#xff0c;我们进入到下一环节员工管理功能的开发。 基于以上原型&#xff0c;我们可以把员工管理功能分为&#xff1a; 分页查询&#xff08;今天完成&#xff09;带条件的分页查询&#xff08;今天完成&#xff09;删除员工&am…

服务器conda环境安装rpy2

参考博客 https://stackoverflow.com/questions/68936589/how-to-select-r-installation-when-using-rpy2-on-conda 现在我遇到这样一个问题&#xff0c;服务器系统环境没有R(没有权限安装&#xff09;&#xff0c;我只能在minconda的conda环境中使用R, 使用方法如下 我现在…

芝法酱学习笔记(0.6)——nexus与maven私库

一、私库的需求 在一个公司中&#xff0c;后端程序员通常几十上百个。在没有镜像私库的情况下&#xff0c;每当引入新库时&#xff0c;大家都会从maven中央仓库下载一遍这个库。这样无疑十分浪费。再加之国家的防火墙政策&#xff0c;许多人下载lib包可能还会十分缓慢。不同程…

Python水循环标准化对比算法实现

&#x1f3af;要点 算法区分不同水循环数据类型&#xff1a;地下水、河水、降水、气温和其他&#xff0c;并使用相应标准化降水指数、标准化地下水指数、标准化河流水位指数和标准化降水蒸散指数。绘制和计算特定的时间序列比较统计学相关性。使用相关矩阵可视化集水区和显示空…

推荐:五种限流(Rate Limiting)算法

推荐&#xff1a;五种限流(Rate Limiting)算法&#xff0c;发现一个不错的讲这个算法的UP,地址是&#xff1a;05~五种限流(Rate Limiting)算法_哔哩哔哩_bilibili https://www.bilibili.com/video/BV11k4SerE74/ 全部用动画展示&#xff0c;十分生动&#xff0c;比如漏桶算法&…

短剧小程序短剧APP在线追剧APP网剧推广分销微短剧小剧场小程序集师知识付费集师短剧小程序集师小剧场小程序集师在线追剧小程序源码

一、产品简介功能介绍 集师专属搭建您的独有短剧/追剧/小剧场小程序或APP平台 二、短剧软件私域运营解决方案 针对短剧类小程序的运营&#xff0c;以下提出10条具体的方案&#xff1a; 明确定位与目标用户&#xff1a; 对短剧类小程序进行明确定位&#xff0c;了解目标用户群体…

【AI知识点】置信区间(Confidence Interval)

置信区间&#xff08;Confidence Interval, CI&#xff09; 是统计学中用于估计总体参数的范围。它给出了一个区间&#xff0c;并且这个区间包含总体参数的概率等于某个指定的置信水平&#xff08;通常是 90%、95% 或 99%&#xff09;。与点估计不同&#xff0c;置信区间通过区…

开源的云平台有哪些?

开源云平台为用户提供了构建、管理和运行云基础设施及应用的能力&#xff0c;同时允许社区参与开发和改进。以下是一些知名的开源云平台&#xff1a; 1. OpenStack 简介&#xff1a;OpenStack&#xff1a;一个广泛使用的开源云平台&#xff0c;它由多个组件组成&#xff0c;提…

深度学习中的结构化概率模型 - 结构化概率模型的深度学习方法篇

序言 在深度学习的广阔领域中&#xff0c;结构化概率模型&#xff08; Structured Probabilistic Model \text{Structured Probabilistic Model} Structured Probabilistic Model&#xff09;扮演着至关重要的角色。这类模型利用图论中的图结构来表示概率分布中随机变量之间的…

精品WordPress主题/响应式个人博客主题Kratos

Kratos 是一款专注于用户阅读体验的响应式 WordPress 主题&#xff0c;整体布局简洁大方&#xff0c;针对资源加载进行了优化。 Kratos主题基于Bootstrap和Font Awesome的WordPress一个干净&#xff0c;简单且响应迅速的博客主题&#xff0c;Vtrois创建和维护&#xff0c; 主…

Markdown实用语法汇总

说明&#xff1a; 本来只展示本人常用的、markdown特有优势的一些语法。表格输入markdown的弱项&#xff0c;不作介绍&#xff0c;借助软件创建即可。引用图片、音频、视频等&#xff0c;虽然很方便&#xff0c;但是内容集成度不高&#xff0c;需要上传发布的时候很不方便&…

学习C语言(23)

整理今天的学习内容 1.文件的概念 使用文件是为了将数据永久化地保存 按照文件功能&#xff0c;在程序设计中一般把文件分成两类&#xff1a; 每个文件都有一个唯一的文字标识&#xff0c;文字标识常被称为文件名&#xff0c;文件名包含文件路径&#xff0c;文件名主干和文件…

Apollo9.0 Planning2.0决策规划算法代码详细解析 (4): PlanningComponent::Proc()

&#x1f31f; 面向自动驾驶规划算法工程师的专属指南 &#x1f31f; 欢迎来到《Apollo9.0 Planning2.0决策规划算法代码详细解析》专栏&#xff01;本专栏专为自动驾驶规划算法工程师量身打造&#xff0c;旨在通过深入剖析Apollo9.0开源自动驾驶软件栈中的Planning2.0模块&am…

vAPI靶场

前言 自行去搭建vAPI靶场&#xff0c;配合postman使用 vapi1 创建用户 第一个用户 {"username": "shi","name": "shi1","course": "nihao","id": 10 } 第二个用户 {"username": "hui…

论文理解【LLM-CV】—— 【MAE】Masked Autoencoders Are Scalable Vision Learners

文章链接&#xff1a;Masked Autoencoders Are Scalable Vision Learners代码&#xff1a;GitHub - facebookresearch/mae发表&#xff1a;CVPR 2022领域&#xff1a;LLM CV一句话总结&#xff1a;本文提出的 MAE 是一种将 Transformer 模型用作 CV backbone 的方法&#xff0c…