【微服务】网关(详细知识以及登录验证)

微服务网关

  • 网关
    • 网关路由
      • 快速入门
      • 路由属性
    • 路由断言
    • 网关登录校验
      • 自定义过滤器
      • 实现登录校验
      • 网关传递用户
      • OpenFeign传递用户

网关

网络的关口,负责请求的路由,转发,身份校验

当我们把一个单体项目分成多个微服务并部署在多台服务器中,这时由于地址的不同,可能出现身份校验,地址过多等问题

我们通过网关,将微服务集群统一在一个网关之下,并在通过注册中心将服务拉取到网关之中,自此我们直接访问网关,由网关进行对应微服务的路由转发和身份校验

在SpringCloud中网关的实现包括两种:
Spring Cloud Gateway:基于WebFlux响应式编程,无需调优即可获取优异性能
Netflix:基于Servlet的阻塞式编程,需要调优才能获取与SpringCloudGateway类似的性能

网关路由

快速入门

网关判断由哪个微服务进行处理的过程就是网关路由

  1. 引入依赖网关,Nacos,Loadbalancer
        <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>org.springframework.boot</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
  1. 创建一个新的网关微服务模块,并创建启动类
@SpringBootApplication
public class GatewayApplication{public static void main(String[] args){SpringApplication.run(GatewayApplication.Class,args);}
}
  1. 配置网关配置
server:port: 8080
spring:application:name: gatewaycloud:nacos:server-addr: 服务器地址:8848gateway:routes:-id: 对应的服务名称uri: lb://服务名称  # lb意思是负载均衡predicates:- Path=/路径名称/**# 配置多个路由-id:

路由属性

网关路由对应的java类型是RouteDefinition,其中常见的属性:
id:路由的唯一标识
uri:路由的目标地址
predicates:路由断言,判断请求是否符合当前路由
filters:路由过滤器,对请求或响应做特殊处理

路由断言

Spring提供了12种基本的RoutePredicateFactory实现:
在这里插入图片描述
网关提供了很多的路由过滤器,每种过滤器都有独特的作用:
在这里插入图片描述
对应的过滤器可以在配置文件中进行配置

网关登录校验

在这里插入图片描述
此处为网关内部的处理逻辑,我们要进行登录校验的处理需要在过滤器的最前面添加一个自定义的过滤器,在pre阶段进行登录校验
校验成功之后,网关如何将信息传递给微服务:

将用户信息保存到请求头当中进行传递

微服务之间该如何传递校验信息:

也是保存信息到请求头当中,但是请求头的发送是由Openfeign来实现的

自定义过滤器

网关过滤器有两种:
GatewayFilter:路由过滤器,作用于任意指定的路由,默认不生效,要配置到路由后生效(在配置文件中进行配置)
GlobalFilter:全局过滤器,作用范围是所有路由,声明后自动生效(自定义之后在配置文件中使用)
我们这里通过GlobalFilter进行登录校验的实现

public interface GlobalFilter{Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain);
}

通过这个方法实现过滤器中的操作,第一个参数是请求上下文,包含整个过滤器链中的共享数据,比如request,response等等,第二个参数是过滤器链,当前过滤器执行完成之后,要调用过滤器中的下一个过滤器

网关采用非阻塞式的编程,Mono中编写一个回调函数,当过滤器将来执行到POST的时候调用回调函数,过滤器将不再进行长时间的等待

我们实现该接口实现过滤器:

@Component
public class MyGlobalFilter implements GlobalFilter,Ordered{@Overridepublic Mono<void> filter(ServerWebExchange exchange,GatewayFilterChain chain){//利用exchange进行登录校验的逻辑编写//方向,将共享数据传递给下一个过滤器中return chain.filter(exchange);}@Overridepublic int getOrder(){return 0;}
}

注意:查看过滤器链,将鼠标放在GlobalFilter上按ctrl+H

实现Ordered接口,重写getOrder方法,返回的值越小,则过滤器在过滤器链中的优先级越高

自定义之后在配置文件中进行配置使用:

spring:cloud:gateway:default-filters:-AddRequestHeader=a,b

通常我们使用上述的自定义过滤器,但是还有一种过滤器GatewayFilter自定义过滤器,使用过滤器工厂AbstractGateWayFilterFactory:

@Component
public class GLQFilterFactory extends AbstractGatewayFilterFactory<Object>{@Overridepublic GatewayFilter apply(Object config){return new GatewayFilter(new GatewayFilter(){@Overridepublic Mono<void> filter(ServerWebExchange exchange,GatewayFilterChain chain){//编写过滤器逻辑//放行return chain.filter(exchange);}}1);}
}

自定义过滤器类的类名的前缀就是将来的过滤器的名字,而后半部分应该是类名

实现登录校验

在这里插入图片描述

@Component
public class AuthGlobalFilter implements GlobalFilter,Ordered{//不用登录校验的地址实体类private final AuthProperties authproperties;private final JWtTool jwttool;//spring提供的匹配工具类private final AntPathMatcher antpathMatcher=new AntPathMatcher();@Overridepublic Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain){//获取requestServerHttpRequest request= exchange.getRequest();//判断是否需要做登录校验(向注册,登录界面就不需要做登录校验)if(isExclude(request.getPath().toString())){//放行return chain.filter(exchange);}//获取tokenString token=null;List<String> headers=request.getHeaders().get("token");if(headers !=null && !headers.isEmply()){token=headers.get(0);}//利用jwt工具类校验tokentry{Long userid=jwttool.parseToken(token);}catch (UnauthorizedException e){//拦截设置响应状态码为401(未登录)ServerHttpResponse response=exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);}//放行return chain.filter(exchange);}private  boolean isExclude(String path){for(String pathPattern : authProperties.getExcludePaths()){if(antPathMatcher.match(pathPattern,path)){return true;}}return false;}@Overridepublic int getOrder(){return 0;}
}

网关传递用户

前面所将的需要将信息传递给的微服务,需要将信息保存到请求头中,而在微服务中需要设置拦截器将所有用户信息保存到ThreadLocal中

如何向微服务中进行传递,需要略微修改上述所讲的过滤器:

     @Overridepublic Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain){//获取requestServerHttpRequest request= exchange.getRequest();//判断是否需要做登录校验(向注册,登录界面就不需要做登录校验)if(isExclude(request.getPath().toString())){//放行return chain.filter(exchange);}//获取tokenString token=null;List<String> headers=request.getHeaders().get("token");if(headers !=null && !headers.isEmply()){token=headers.get(0);}//利用jwt工具类校验tokentry{Long userid=jwttool.parseToken(token);}catch (UnauthorizedException e){//拦截设置响应状态码为401(未登录)ServerHttpResponse response=exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);}//保存到请求头中,传递给微服务String userinfo=userid.toString();ServerWebExchange ww=exchange.mutate().request(builder->builder.header("user-info",userinfo)).build();//放行return chain.filter(ww);}

将拦截器单独写在一个微服务当中,这样避免代码冗余:

public class UserInfoInterceptor implements	HandlerInterceptor{@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler) throws Exception{//获取登录信息String userInfo=request.getHeader("user-info");//判断是否获取了用户,如果有,存入ThreadLocalif(StrUtil.isNotBlank(userInfo)){//存入到ThreadLocal中}// 放行return true;}@Overridepublic void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex) throws Exception{}
}

创建好之后在继承了WebMvcConfigurer的配置类中添加拦截器
这时别的微服务还是用不了拦截器,因为它配置类的包没有被扫到,这时我们需要将添加拦截器的配置类放到resources目录下的META-INF文件中添加配置类

@Configuration
@ConditionalOnClass(DispatcherServlet.class)
public class MvcConfig implements WebMvcConfigurer{ @Overridepublic void addInterceptors(InterceptorRegistry registry){registry.addInterceptor(new UserInfoInterceptor());}
}

注意:如果运行的时候网关模块报错

是因为网关的底层不是SpringMVC,而是响应式编程,而WebMvcConfigurer是MVC中提供的,所以我们在配置类上方添加注解,当有MVC的核心api就是DispatcherServlet,拥有这个的微服务该配置类生效

OpenFeign传递用户

微服务项目中的很多业务要被多个微服务共同合作完成,而这个过程中也需要传递登录用户信息
openFeign中提供了一个拦截器接口,所有有Openfeign发起的请求都会先调用拦截器处理请求

将此拦截器写在当时定义的Openfeign的微服务项目中,以便日后统一调用

public class Myconfig{@Beanpublic RequestInterceptor userinterceptor(){return new RequestInterceptor(){@Overridepublic void apply(RequestTemplate template){//将添加请求头信息Long userid=Usercontext.getUser();if(userid!=null){template.header("user-info",userid.toString()) ;}}}}
}

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

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

相关文章

运动控制“MC_MoveVelocity“功能块详细应用介绍

1、运动控制单位u/s介绍 运动控制单位[u/s]介绍-CSDN博客文章浏览阅读91次。运动控制很多手册上会写这样的单位,这里的u是英文单词unit的缩写,也就是单位的意思,所以这里的单位不是微米/秒,也不是毫米/秒,这里是一个泛指,当我们的单位选择脉冲时,它就是脉冲/秒,也就是…

如何解决3D模型变黑或贴图不显示的问题---模大狮模型网

在进行3D建模和视觉渲染时&#xff0c;经常会遇到模型表面变黑或贴图不显示的问题&#xff0c;这可能严重影响最终视觉效果的质量。这些问题通常与材质设置、光照配置或文件路径错误有关。本文将探讨几种常见原因及其解决方法&#xff0c;帮助3D艺术家和开发者更有效地处理这些…

3D相机及应用

无论是2D相机和3D相机&#xff0c;在工业应用中都有着不可或缺的作用。3D相机与2D相机的最大区别在于&#xff0c;3D相机可以获取真实世界尺度下的3D信息&#xff0c;而2D相机只能获取像素尺度下的2D平面图像信息。通过3D相机得到的数据&#xff0c;我们可以还原出被测量物体的…

最新版Ceph( Reef版本)块存储简单对接k8s

当前ceph 你的ceph集群上执行 1.创建名为k8s-rbd 的存储池 ceph osd pool create k8s-rbd 64 642.初始化 rbd pool init k8s-rbd3 创建k8s访问块设备的认证用户 ceph auth get-or-create client.kubernetes mon profile rbd osd profile rbd pool=k8s-rbd部署 ceph-rbd-csi …

Devin AI程序员是如何设计出来的

背景 Devin是一个能够执行复杂工程任务并与用户在软件开发项目上积极合作的自主人工智能软件工程师&#xff0c;它擅长planning、tool use、reflecting&#xff0c;碾压大部分初级开发。 设计思路 一、界面设计 先来看 Devin 的界面&#xff0c;左边是对话框&#xff0c;记…

基于51单片机ESP8266wifi控制机器人—送餐、快递

基于51单片机wifi控制机器人 &#xff08;程序&#xff0b;原理图&#xff0b;PCB&#xff0b;设计报告&#xff09; ​功能介绍 具体功能&#xff1a; 1.L298N驱动电机&#xff0c;机器人行走&#xff1b; 2.装备红外线感应检测到周围环境&#xff0c;进行行程判断&#xf…

Python Dash库:一个Web应用只需几行代码

大家好&#xff0c;在数据科学领域&#xff0c;数据可视化是将数据以图形化形式展示出来&#xff0c;帮助我们更直观地理解数据。Python中有一个非常流行的数据可视化库叫做Dash&#xff0c;Dash以其简洁、高效和强大的功能而闻名&#xff0c;它允许开发者快速构建交互式Web应用…

Markdown 精简教程(胎教级教程)

文章目录 一、关于 Markdown1. 什么是 Markdown&#xff1f;2. 为什么要用 Markdown&#xff1f;3. 怎么用 Markdown&#xff1f;&#xff08;编辑软件&#xff09; 二、标题1. 常用标题写法2. 可选标题写法3. 自定义标题 ID4. 注意事项 三、段落四、换行五、字体选项1. 粗体2.…

Map集合的实现类~HashMap

存储结构&#xff1a;哈希表 键重复依据是hashCode和equals方法&#xff08;键不能重复&#xff09; 添加&#xff1a; 先创建Student类&#xff0c;那么往HashSet添加的就是Student对象作为键值&#xff0c;后面的作为值 删除&#xff1a; 判断&#xff1a; 遍历&#xff1a…

第五节 内联框架强化练习

建立左右常用框架结构说明 1、添加动态面板如下&#xff1a; 2、添加树元件 3、添加树节点&#xff08;右键->添加子节点 右键->点添加节点&#xff09; 4、添加交互页面 5、添加单击交互跳转事件到内联框架中(注意当前内联框架与当前面板要处在同级目录) 6、添加交互跳…

深度学习实战76-基于目标检测YOLOv5模型的迁移学习使用方法,YOLOv5的原理与结构

大家好,我是微学AI,今天给大家介绍一下深度学习实战76-基于目标检测YOLOv5模型的迁移学习使用方法,YOLOv5的原理与结构。YOLOv5(You Only Look Once version 5)是一种先进的目标检测算法,基于深度学习的单阶段目标检测模型。它的主要原理是通过一次前向传播就同时预测图像…

Springboot项目学习之各组件的用法和逻辑结构

1.Controller层&#xff08;Controller&#xff09;&#xff1a; 也称为前端控制器或请求处理器&#xff0c;它是项目与用户交互的入口。Controller接收HTTP请求&#xff0c;解析请求参数&#xff0c;调用Service层处理业务逻辑&#xff0c;并返回响应给客户端。 Controller通…