一般系统的请求认证授权思路【gateway网关+jwt+redis+请求头httpheader】

gateway:网关,我们都知道网关的作用就是对系统的所有请求,网关都会进行拦截,然后做一些操作(例如:设置每个请求的请求头httpHeader,身份认证等等)此时一般会使用到网关过滤器,创建一个过滤器去实现GlobalFilter接口

jwt:JSON-WEB-TOKEN,这里就不过多解释了,同学们可以自行搜索相关文章,它主要包含三个部分,更好的生成token的一种行业规范,主要作用就是令牌校验。

{

        header:xxx,

        payload:xxx,

        singature:xxx

}

redis的主要作用就是为了存放用户信息,该用户信息主要包含以下几个字段

{userCode:xxx,language:xxx,主要是为了进行国际化语言配置比如ZH-CN 、ENmenuApu:["xxx","xxx",..."xxx"] 用户对应的菜单权限列表APIjwtToken:xxx 必须拥有这个字段,为了防止同一个用户在不同机器上登录进行操作
}

httpHeader的主要作用就是存放userCode,用于任何请求都可以获取到当前操作的用户名,比如当我要添加一个新增接口或者更新接口,一般会有两个字段,一个是creator,一个是modifier,那么这两个值就可以直接取请求头的userCode。

还有就是存放language,为了进行国际化语言切换。

所以现在我先给大家画一个图,待会写的代码也是按照这个逻辑,方便大家加深理解与记忆。

现在看一下代码逻辑:

我们创建一个gateway全局过滤器:AuthTokenGlobalFilter

实现GlobalFilter接口,重写如下方法:

public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();HttpHeaders headers = request.getHeaders();//得到前端访问请求时的请求头HttpHeaders httpHeaders = new HttpHeaders();httpHeaders.putAll(headers);//先过滤掉登录请求,登录请求不需要进行拦截,直接放行if (ObjectUtil.equals(request.getURI().getPath(), "/login")) {//放行之前将前端发出请求时的请求头拿到,同时设置一下Accept-LanguagehttpHeaders.setAcceptLanguage(httpHeaders.getAcceptLanguage());//放行chain.filter(exchange.mutate().request(decorateRequest(request, httpHeaders)).build());}//其他请求//判读1:请求的请求头中是否携带tokenif (CollectionUtils.isEmpty(headers.get("Authorization"))) {throw new ServiceException(Codes.NO_TOKEN_RECOGNIZED);//未识别到token}//判断2:token解析出来的数据是否能在redis中查询到,考虑到token有可能发生过期,或者是登出了,redis中的数据就会删除String authorization = headers.get("Authorization").get(0);//通过token 利用jwt反解析出数据 claimsJSONObject jsonObject = JwtUtils.parseJwtToken(authorization, "user", NetworkUtils.getIp(request));if (ObjectUtil.isNull(jsonObject)) {throw new ServiceException(Codes.AUTHORIZATION_ERROR);}//如果是登出请求/logout,需要在请求头中加上userCode,为了后续放行之后,拿到该userCode作为redis的key的一部分去删除登录时存到redis中的数据if (ObjectUtil.equals(request.getURI().getPath(), "/logout")) {httpHeaders.set("userCode", jsonObject.get("userCode").toString());return chain.filter(exchange.mutate().request(decorateRequest(request, httpHeaders)).build());}//拿到userCodeString userCode = (String) jsonObject.get("userCode");//去redis中获取数据 key=》 User:userCode 比如User:zkwString key = USER_CACAHE_PREFIX + userCode;String jsonString = stringRedisTemplate.opsForValue().get(key);LoginUser loginUser = JSONObject.parseObject(jsonString, LoginUser.class);if (ObjectUtils.isEmpty(loginUser)) {throw new ServiceException(Codes.LOGIN_EXPIRED);}//走到这里//1、发出的请求的请求头中携带了token//2、携带的token有效,没有过期或者是登出//那么此时还需要进行判断3,判断携带的token与redis中存储的token是否一致,因为有可能有这么一个情况// A用户在机器172.16.254.1上登录一次,成功之后,就会在redis中存放A对应的token以及其他一些字段数据,//那么此时在A发出另外一个请求之前,比如查询,此时A用户又在另外一台机器上172.16.254.2登录,成功之后,也会在redis中存放A在172.16.254.2对应的token以及其他一些字段数据,此时就会覆盖前面redis中存放A在172.16.254.1的token数据了,// 因为生成的token是有根据ip地址的,所以当A用户在机器上172.16.254.1发起请求的时候,携带的token就与此时redis中的token是不对的了,所以对于这种情况我们就不允许存在。if (!ObjectUtil.equals(authorization, loginUser.getJwtToken())) {throw new ServiceException(Codes.LOGIN_EXPIRED);}//如果token都满足情况了,就代表确确实实身份无误了,那么就需要进行用户的权限列表判断了。}

上面是认证逻辑,现在是授权逻辑了。

redis中有两个key,一个key就是刚刚关于认证token的,另一个就是授权的。AccessControl:permissions,这个key的主要作用就是看看前端发出的请求是否是系统里面已经配置的菜单权限API,防止随意伪造请求API。

接下来我们看看授权的代码:

//***********************************************授权*************************************************************//异步获取统里面配置的存在的菜单api,在redis中有存放两个key,一个key就是刚刚前面关于token的,另外一个是关于菜单权限api的//AccessControl:permissionsMenu 这个值的主要作用就是为了判断你请求的api是否此时系统里面有,如果没有的话,有两个原因://  1、你xjb自己随便别写一个请求 2、确确实实开发了这个接口,但是可能在系统菜单表里面忘记添加了//User:userCodeCompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {return stringRedisTemplate.opsForValue().get("AccessControl:permissionsMenu");});String permissionsMenu = future.join();//如果不为空,就代表此时系统里面已经配置了菜单权限apiif (permissionsMenu != null) {String[] urls = permissionsMenu.split(",");//当前url不存在系统配置的菜单权限api里面 直接放行if (Arrays.stream(urls).noneMatch(part -> (part.trim()).equals(requestPath))) {return chain.filter(exchange.mutate().request(decorateRequest(request, httpHeaders)).build());}}//如果菜单为空,证明是第一次请求到,把系统里面配置的存在的api设置到该key上else {//通过openFeign远程调用获取系统配置的菜单权限APIList<String> urls = permissionFeign.queryPermissionsMenu();stringRedisTemplate.opsForValue().set("AccessControl:permissionsMenu", urls.toString());//当前url不存在系统配置的菜单权限api里面 直接放行if (urls.stream().noneMatch(part -> (part.trim()).equals(requestPath))) {return chain.filter(exchange.mutate().request(decorateRequest(request, httpHeaders)).build());}}//如果存在,如果判断当前用户是否拥有这个菜单权限apiboolean flag = sysMenuService.queryUserMenuButton(userCode).stream().anyMatch(arg -> ObjectUtil.equals(arg.getApi(), requestPath));if (!flag) {throw new ServiceException(Codes.USER_INSUFFICIENT_PERMISSIONS);}return chain.filter(exchange.mutate().request(decorateRequest(request, httpHeaders)).build());

完整代码:

注意:

登录接口是不需要进行拦截的,我们在登录接口的时候,如果登录成功,才会生成一个token(生成token以及代码中的反解析token在我上一篇文章的工具类有,同学们也可以去看一下)还有查询该用户对应的菜单权限API列表,然后会把相关信息存到redis中去。

总结:

最后:

如果大家觉得这篇文章对你们有所帮助的话,麻烦给个免费的赞赞,也祝各位码农在未来的IT道路上越走越远,谢谢!

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

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

相关文章

【echarts】动态滚动趋势图,解决坐标轴数据太多遮挡覆盖问题

写在前面 业务场景x轴的文字太多&#xff0c;会出现遮挡问题&#xff0c;想到文字倾斜展示&#xff0c;页面不美观&#xff0c;于是想到使用滚动条优化趋势图。 <template><div id"storeDown" style"height: 400px;width:100%"/> </temp…

基于SpringBoot的后端导出Excel文件

后端导出Excel&#xff0c;前端下载。 系列文章指路&#x1f449; 系列文章-基于SpringBoot3创建项目并配置常用的工具和一些常用的类 文章目录 后端导出Excel引入依赖写入响应 前端下载后端导出失败和成功返回的内容类型不同&#xff0c;因此需要分别判断。 工具类ServletUti…

GLIP:零样本学习 + 目标检测 + 视觉语言大模型

GLIP 核心思想GLIP 对比 BLIP、BLIP-2、CLIP 主要问题: 如何构建一个能够在不同任务和领域中以零样本或少样本方式无缝迁移的预训练模型&#xff1f;统一的短语定位损失语言意识的深度融合预训练数据类型的结合语义丰富数据的扩展零样本和少样本迁移学习 效果 论文&#xff1a;…

docker核心技术

一. 从系统架构谈起 传统分层架构 vs 微服务 微服务改造 分离微服务的方法建议: 审视并发现可以分离的业务逻辑业务逻辑,在对业务领域不是特别熟悉的时候,按照部门职能进行划分,例如账号、财务等寻找天生隔离的代码模块,可以借助于静态代码分析工具如果可以闭环的解决一…

SQL Server之DML触发器

一、如何创建一个触发器呢 触发器的定义语言如下&#xff1a; CREATE [ OR ALTER ] TRIGGER trigger_nameon {table_name | view_name}{for | After | Instead of }[ insert, update,delete ]assql_statement从这个定义语言我们可以知道如下信息&#xff1a; trigger_name&…

从领域外到领域内:LLM在Text-to-SQL任务中的演进之路

导语 本文介绍了ODIS框架&#xff0c;这是一种新颖的Text-to-SQL方法&#xff0c;它结合了领域外示例和合成生成的领域内示例&#xff0c;以提升大型语言模型在In-context Learning中的性能。 标题&#xff1a;Selective Demonstrations for Cross-domain Text-to-SQL会议&am…

计算机组成原理 — 存储器(1)

存储器 大家好呀&#xff01;我是小笙&#xff0c;由于存储器这部分章节内容较多&#xff0c;我分成二部分进行总结&#xff0c;以下是第一部分&#xff0c;希望内容对你有所帮助&#xff01; 概述 存储器是计算机系统中的记忆设备&#xff0c;用来存放程序和数据 存储器分…

vue3 mathjax 数学公式

安装 pnpm install mathjax 新建文件/util/mathjax.js window.MathJax {tex: {inlineMath: [["$", "$"],["\\(", "\\)"],], // 行内公式选择符displayMath: [["$$", "$$"],["\\[", "\\]"…

UE4运用C++和框架开发坦克大战教程笔记(十七)(第51~54集)

UE4运用C和框架开发坦克大战教程笔记&#xff08;十七&#xff09;&#xff08;第51~54集&#xff09; 51. UI 框架介绍UE4 使用 UI 所面临的问题以及解决思路关于即将编写的 UI 框架的思维导图 52. 管理类与面板类53. 预加载与直接加载54. UI 首次进入界面 51. UI 框架介绍 U…

《合成孔径雷达成像算法与实现》Figure6.4

clc clear close all参数设置 距离向参数设置 R_eta_c 20e3; % 景中心斜距 Tr 2.5e-6; % 发射脉冲时宽 Kr 20e12; % 距离向调频率 alpha_os_r 1.2; % 距离过采样率 Nrg 320; % 距离线采样数 距离向…

CSS布局

CSS布局 1. 版心 在 PC 端网页中&#xff0c;一般都会有一个固定宽度且水平居中的盒子&#xff0c;来显示网页的主要内容&#xff0c;这是网页的版心。版心的宽度一般是 960 ~ 1200 像素之间。版心可以是一个&#xff0c;也可以是多个。 2. 常用布局名词 3. 重置默认样式 很…

C#验证字符串的长度,用正则表达式 vs 字符数组长度或字符串的长度

目录 一、使用的方法 1.使用正则表达式 2.通过计算字符串的长度验证 二、实例 1.源码 2.生成效果 一、使用的方法 1.使用正则表达式 使用正则表达式可以判断和限制用户输入的字符串长度。 比如验证用户密码不得少于8为&#xff0c;匹配的正则表达式"^.{8,}$"…

AIGC专题:AIGC教育行业全景报告

今天分享的是AI GC系列深度研究报告&#xff1a;《AIGC专题&#xff1a;AIGC教育行业全景报告》。 &#xff08;报告出品方&#xff1a;量子位智库&#xff09; 报告共计&#xff1a;31页 生成式AI快速落地教育&#xff0c;技术推动教育理念实施 生成式AI将我们带入AI2.0时代…

数据类型完整版

第三章 数据类型 3.1 Key操作 3.1.1 相关命令 序号命令语法描述1DEL key该命令用于在 key 存在时删除 key2DUMP key序列化给定 key &#xff0c;并返回被序列化的值3EXISTS key检查给定 key 是否存在&#xff0c;存在返回1&#xff0c;否则返回04EXPIRE key seconds为给定 k…

MacOS系统电脑远程桌面控制windows系统电脑【内网穿透】

最近&#xff0c;我发现了一个超级强大的人工智能学习网站。它以通俗易懂的方式呈现复杂的概念&#xff0c;而且内容风趣幽默。我觉得它对大家可能会有所帮助&#xff0c;所以我在此分享。点击这里跳转到网站。 文章目录 1. 测试本地局域网内远程控制1.1 Windows打开远程桌面1…

回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)

回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&#xff09; 目录 回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测&#xff08;SE注意力机制&…

问题:0xc8前面加(byte) #人工智能#学习方法的原因是因为0xc8大于??????????? 。 #微信#其他#微信

问题&#xff1a;0xc8前面加&#xff08;byte&#xff09;的原因是因为0xc8大于??????????? 。 参考答案如图所示

大数据学习之Redis,十大数据类型的具体应用(五)

目录 3.9 Redis地理空间&#xff08;GEO&#xff09; 简介 原理 Redis在3.2版本以后增加了地理位置的处理哦 命令 命令实操 如何获得某个地址的经纬度 3.9 Redis地理空间&#xff08;GEO&#xff09; 简介 移动互联网时代LBS应用越来越多&#xff0c;交友软件中附近的…

双非本科准备秋招(10.2)—— JVM3:垃圾收集器

垃圾收集器 分为七种&#xff0c;如下&#xff1a; 从功能的角度分为 1、串行&#xff1a;Serial、Serial Old 2、吞吐量优先&#xff1a;Parallel Scavenge、Parallel Old 3、响应时间优先&#xff1a;CMS 吞吐量优先VS响应时间优先 吞吐量运行用户代码时间/(运行用户代码…

如何通过ETL实现快速同步美团订单信息

一、美团外卖现状 美团作为中国领先的生活服务电子商务平台&#xff0c;其旗下的美团外卖每天承载着大量的订单信息。这些订单信息需要及时入库、清洗和同步&#xff0c;但由于数据量庞大且来源多样化&#xff0c;传统的手动处理方式效率低下&#xff0c;容易出错。比如&#…