微服务网关SpringCloudGateway+SaToken鉴权
目录
概念
前置知识回顾
拿到UserInfo 用于自定义权限和角色的获取逻辑
最后进行要进行 satoken 过滤器全局配置
概念
做权限认证的时候 我们首先要明确两点
我们需要的角色有几种 我们需要的权限有几种
角色 分两种
ADMIN 管理员 :可管理商品
CUSTIOMER 普通用户 :
权限 分四种
BASIC 基本权限 :可浏览商品
AUTU 已实名认证权限 :可下单支付
FROZEN 被冻结用户权限
NONE 没有任何权限
前置知识回顾
在阅读完 sa-token 的文档后
我发现原来权限验证如此简单
我们只需要 使用StpUtil即可
这个在开发博客的时候写过相关的
// 用户已存在,直接登录
StpUtil.login(userInfo.getUserId(), new SaLoginModel().setIsLastingCookie(loginParam.getRememberMe()).setTimeout(DEFAULT_LOGIN_SESSION_TIMEOUT));
// 将用户信息存入会话
StpUtil.getSession().set(userInfo.getUserId().toString(), userInfo);
// 创建登录结果对象
LoginVO loginVO = new LoginVO(userInfo);
// 返回登录成功响应
return Result.success(loginVO);
拿到UserInfo 用于自定义权限和角色的获取逻辑
我们在用 StpUtil 去拿这个登录信息
进行校验
很容易理解 我们在登录模块 放入了一个 UserInfo 对象进去
包含了用户了信息
package cn.hollis.nft.turbo.api.user.response.data;import cn.hollis.nft.turbo.api.user.constant.UserRole;
import cn.hollis.nft.turbo.api.user.constant.UserStateEnum;
import com.github.houbb.sensitive.annotation.strategy.SensitiveStrategyPhone;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;import java.util.Date;/*** @author Hollis*/
@Getter
@Setter
@NoArgsConstructor
public class UserInfo extends BasicUserInfo {private static final long serialVersionUID = 1L;/*** 手机号*/@SensitiveStrategyPhoneprivate String telephone;/*** 状态** @see UserStateEnum*/private String state;/*** 区块链地址*/private String blockChainUrl;/*** 区块链平台*/private String blockChainPlatform;/*** 实名认证*/private Boolean certification;/*** 用户角色*/private UserRole userRole;/*** 邀请码*/private String inviteCode;/*** 注册时间*/private Date createTime;public boolean userCanBuy() {if (this.getUserRole() != null && !this.getUserRole().equals(UserRole.CUSTOMER)) {return false;}// 判断买家状态if (this.getState() != null && !this.getState().equals(UserStateEnum.ACTIVE.name())) {return false;}// 判断买家状态if (this.getState() != null && !this.getCertification()) {return false;}return true;}
}
我们sa-token 提供的接口中重写权限校验方法
实现stpInterface 调用处理这个接口方法
我们就是再把这个对象拿出来
// 根据用户登录ID和登录类型返回不同的权限列表
UserInfo userInfo = (UserInfo) StpUtil.getSessionByLoginId(loginId).get((String) loginId);
然后找到权限 返回枚举值
枚举值要包装成 list 类型
这边返回的是List类型
这些文档里都有...
package cn.hollis.nft.turbo.gateway.auth;import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import cn.hollis.nft.turbo.api.user.constant.UserPermission;
import cn.hollis.nft.turbo.api.user.constant.UserRole;
import cn.hollis.nft.turbo.api.user.constant.UserStateEnum;
import cn.hollis.nft.turbo.api.user.response.data.UserInfo;
import org.springframework.stereotype.Component;import java.util.List;/*** 自定义权限验证接口实现类* StpInterface 接口用于自定义权限和角色的获取逻辑。* StpInterfaceImpl 类实现了 StpInterface 接口,通过用户的会话信息动态获取用户的权限和角色列表。* 在 Sa - Token 框架进行权限验证时,会调用该类的方法来确定用户是否具备相应的权限和角色。* 注意:这边通过用户会话信息动态获取用户权限和角色列表** @author Hollis*/
@Component
public class StpInterfaceImpl implements StpInterface {/*** 根据用户的登录 ID 和登录类型获取用户的权限列表** @param loginId 用户的登录 ID* @param loginType 用户的登录类型* @return 用户的权限列表,以字符串集合形式返回*/@Overridepublic List<String> getPermissionList(Object loginId, String loginType) {// 从会话中根据登录 ID 获取用户信息UserInfo userInfo = (UserInfo) StpUtil.getSessionByLoginId(loginId).get((String) loginId);// 如果用户角色是管理员,或者用户状态为激活状态、已认证状态if (userInfo.getUserRole() == UserRole.ADMIN|| userInfo.getState().equals(UserStateEnum.ACTIVE.name())|| userInfo.getState().equals(UserStateEnum.AUTH.name()) ) {// 赋予用户基础权限和认证权限return List.of(UserPermission.BASIC.name(), UserPermission.AUTH.name());}// 如果用户状态为初始状态if (userInfo.getState().equals(UserStateEnum.INIT.name())) {// 赋予用户基础权限return List.of(UserPermission.BASIC.name());}// 如果用户状态为冻结状态if (userInfo.getState().equals(UserStateEnum.FROZEN.name())) {// 赋予用户冻结权限return List.of(UserPermission.FROZEN.name());}// 其他情况,赋予用户无权限return List.of(UserPermission.NONE.name());}/*** 根据用户的登录 ID 和登录类型获取用户的角色列表** @param loginId 用户的登录 ID* @param loginType 用户的登录类型* @return 用户的角色列表,以字符串集合形式返回*/@Overridepublic List<String> getRoleList(Object loginId, String loginType) {// 从会话中根据登录 ID 获取用户信息UserInfo userInfo = (UserInfo) StpUtil.getSessionByLoginId(loginId).get((String) loginId);// 如果用户角色是管理员if (userInfo.getUserRole() == UserRole.ADMIN) {// 返回管理员角色return List.of(UserRole.ADMIN.name());}// 其他情况,返回普通用户角色return List.of(UserRole.CUSTOMER.name());}
}
最后进行要进行 satoken 过滤器全局配置
SaReactorFilter
package cn.hollis.nft.turbo.gateway.auth;import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hollis.nft.turbo.api.user.constant.UserPermission;
import cn.hollis.nft.turbo.api.user.constant.UserRole;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** sa-token的全局配置类,用于配置鉴权过滤器和异常处理逻辑** @author Hollis*/
@Configuration
@Slf4j
public class SaTokenConfigure {/*** 创建并配置 SaReactorFilter 实例,该过滤器用于对请求进行鉴权和异常处理** @return 配置好的 SaReactorFilter 实例*/@Beanpublic SaReactorFilter getSaReactorFilter() {return new SaReactorFilter()// 配置需要拦截的请求地址,/** 表示拦截所有请求.addInclude("/**")// 配置不需要拦截的请求地址,这里排除了网站图标请求.addExclude("/favicon.ico")// 设置鉴权方法,每次请求进入时会执行该方法进行鉴权.setAuth(obj -> {// 登录校验:拦截所有路由,但排除指定的开放路由,对其他请求进行登录状态检查SaRouter.match("/**").notMatch("/auth/**", "/collection/collectionList", "/collection/collectionInfo", "/wxPay/**").check(r -> StpUtil.checkLogin());// 权限认证:针对不同模块的请求,校验不同的权限// 管理界面请求需要用户具备管理员角色SaRouter.match("/admin/**", r -> StpUtil.checkRole(UserRole.ADMIN.name()));// 下单界面请求需要用户具备实名认证权限SaRouter.match("/trade/**", r -> StpUtil.checkPermission(UserPermission.AUTH.name()));// 用户界面请求需要用户具备基本权限或冻结权限SaRouter.match("/user/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(), UserPermission.FROZEN.name()));// 商品界面请求需要用户具备基本权限或冻结权限SaRouter.match("/order/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(),UserPermission.FROZEN.name()));})// 设置异常处理方法,当鉴权方法抛出异常时会进入该方法进行处理.setError(this::getSaResult);}/*** 根据不同的异常类型,返回相应的错误信息** @param throwable 捕获到的异常对象* @return 封装了错误信息的 SaResult 对象*/private SaResult getSaResult(Throwable throwable) {switch (throwable) {// 处理用户未登录异常case NotLoginException notLoginException:// 记录错误日志log.error("请先登录");// 返回未登录的错误信息return SaResult.error("请先登录");// 处理用户角色不匹配异常case NotRoleException notRoleException:// 判断是否是管理员角色权限问题if (UserRole.ADMIN.name().equals(notRoleException.getRole())) {// 记录越权使用的错误日志log.error("请勿越权使用!");// 返回越权使用的错误信息return SaResult.error("请勿越权使用!");}// 记录无权限操作的错误日志log.error("您无权限进行此操作!");// 返回无权限操作的错误信息return SaResult.error("您无权限进行此操作!");// 处理用户权限不足异常case NotPermissionException notPermissionException:// 判断是否是实名认证权限问题if (UserPermission.AUTH.name().equals(notPermissionException.getPermission())) {// 记录需要实名认证的错误日志log.error("请先完成实名认证!");// 返回需要实名认证的错误信息return SaResult.error("请先完成实名认证!");}// 记录无权限操作的错误日志log.error("您无权限进行此操作!");// 返回无权限操作的错误信息return SaResult.error("您无权限进行此操作!");// 处理其他未知异常default:// 返回异常的错误信息return SaResult.error(throwable.getMessage());}}
}
相关文章:

微服务网关SpringCloudGateway+SaToken鉴权
目录 概念 前置知识回顾 拿到UserInfo 用于自定义权限和角色的获取逻辑 最后进行要进行 satoken 过滤器全局配置 概念 做权限认证的时候 我们首先要明确两点 我们需要的角色有几种 我们需要的权限有几种 角色 分两种 ADMIN 管理员 :可管理商品 CUSTIOMER 普通…...

永磁同步电机控制算法--模糊PI转速控制器
一、原理介绍 在常规的PID控制系统的基础上提出了一种模糊PID以及矢量变换方法相结合的控制系统,经过仿真分析对比证明: 模糊PID控制系统能够有效的提高永磁同步电机的转速响应速度,降低转矩脉动,增强了整体控制系统的抗干扰能力…...

Elasticsearch集群最大分片数设置详解:从问题到解决方案
目录 前言 1 问题背景:重启后设置失效 2 核心概念解析 2.1 什么是分片(Shard)? 2.2 cluster.max_shards_per_node的作用 2.3 默认值是多少? 3 参数设置的两种方式 3.2 持久性设置(persistent) 3.2 临时设置(transient) 4 问题解决方…...
计算机视觉与深度学习 | 基于MATLAB的图像特征提取与匹配算法总结
基于MATLAB的图像特征提取与匹配算法全面指南 图像特征提取与匹配 基于MATLAB的图像特征提取与匹配算法全面指南一、图像特征提取基础特征类型分类二、点特征提取算法1. Harris角点检测2. SIFT (尺度不变特征变换)3. SURF (加速鲁棒特征)4. FAST角点检测5. ORB (Oriented FAST …...

DVWA全靶场
目录 暴破 Low - 万能密码 Medium - 转义 High - Token Impossible 命令注入 CSRF跨站请求伪造 - 抓包 Low Medium - 域名限制 High - 域名限制xss 文件包含 - 页面点点点 Low Medium - 过滤http:// High - file Impossible - 写死 文件上传 Low Medium - 文件…...

【反无人机检测】C2FDrone:基于视觉Transformer网络的无人机间由粗到细检测
C2FDrone:基于视觉Transformer网络的无人机间由粗到细检测 C2FDrone: Coarse-to-Fine Drone-to-Drone Detection using Vision Transformer Networks 论文链接 摘要 摘要——基于视觉的无人机间检测系统在碰撞规避、反制敌对无人机和搜救行动等应用中至关重要。然…...

Android 本地存储路径说明
一、背景 作为一个开发者,我们经常需要通过缓存一些文件到SD卡中,常见的方式就是,通过: File sdCard Environment.getExternalStorageDirectory(); 获取SD卡根目录,然后自定义文件/文件名进行文件存储.这样做法的结果就是,当手机安装了大量的app时,SD卡根目录会…...
Git 推送失败解决教程——error: failed to push some refs to
🚧 Git 推送失败解决教程: 错误信息: error: failed to push some refs to ... hint: Updates were rejected because the remote contains work that you do not have locally.🧠 问题原因简述: 你的本地分支试图将…...
spark 执行 hive sql数据丢失
spark-sql 丢失数据 1.通过spark执行hive sql 的时候,发现 hive 四条数据,spark 执行结果只有两条数据 目标对应的两条数据丢失 select date, user_id, pay from dim.isr_pay_failed where user_id ‘*******’ hive-sql 结果…...

国产pcie switch 8748+飞腾/龙芯/昇腾高速存储方案设计
方案概述 本设计以国微PCIe Switch 8748为核心交换芯片,通过多端口PCIe 4.0/5.0通道连接飞腾ARM架构处理器、龙芯LoongArch处理器及昇腾AI加速卡,构建支持NVMe协议的高速存储集群,目标实现6.5GB/s以上的可持续带宽。 硬件架构 处理器选型 飞…...
【Qt】:设置新建类模板
完整的头文件模板 #ifndef %FILENAME%_H #define %FILENAME%_H/*** brief The %CLASSNAME% class* author %USER%* date %DATE%*/ class %CLASSNAME% { public:%CLASSNAME%();~%CLASSNAME%();// 禁止拷贝构造和赋值%CLASSNAME%(const %CLASSNAME%&) delete;%CLASSNAME%&a…...

如何使用插件和子主题添加WordPress自定义CSS(附:常见错误)
您是否曾经想更改网站外观的某些方面,但不知道怎么做?有一个解决方案——您可以将自定义 CSS(层叠样式表)添加到您的WordPress网站! 在本文中,我们将讨论您需要了解的有关CSS的所有知识以及如何使用它来修…...

开始在本地部署自己的 Gitea 服务器
0.简介 在软件开发和团队协作中,代码管理是至关重要的环节。笔者一直使用gitblit管理自己的仓库。然鹅,这个软件已经很久没有更新了。经过多方考察,发现Gitea 是一款轻量级的开源代码托管平台,具有易于部署、资源占用少、功能丰富…...

7.2.1_顺序查找
知识总览: 顺序查找: 算法思想: 从头到脚挨个找或者从脚到头挨个找适用于线性表(顺序存储和链式存储都适用),又叫线性查找 实现: 1个数组elem指向数组的起始位置,索引从0开始遍历数组直到找到目标值返回…...
spring重试机制
数据库死锁处理与重试机制实现指南 1. 业务场景 1.1 问题现象 高并发批量数据处理时频繁出现数据库死锁主要发生在"先删除历史数据,再重新计算"的业务流程中原有逐条处理方式:list.forEach(item -> { delete(); calculate(); }) 1.2 死…...
C语言的全称:(25/6/6)
C语言,全称为"C Programming Language"(C程序设计语言),是一种广泛使用的计算机编程语言。它是由Dennis Ritchie于1972年在贝尔实验室设计的,继承了B语言的许多思想,并加入了数据类型的概念及其他…...

智能制造数字孪生全要素交付一张网:智造中枢,孪生领航,共建智造生态共同体
在制造业转型升级的浪潮中,数字孪生技术正成为推动行业变革的核心引擎。从特斯拉通过数字孪生体实现车辆全生命周期优化,到海尔卡奥斯工业互联网平台赋能千行百业,数字孪生技术已从概念验证走向规模化落地。通过构建覆盖全国的交付网络&#…...

stylus - 新生代CSS预处理框架
stylus是什么 Stylus 是一种 CSS 预处理器,它扩展了 CSS 的功能,使得编写样式变得更简洁和高效。Stylus 允许使用嵌套、变量、混入等编程功能,这些功能可以极大地提高开发效率和代码的可维护性。 stylus中文文档 https://stylus.uihtm.co…...
python八股文算法:三数之和
双指针解法: 原理见注释 # 2025/6/6 9:40 # -*- coding:UTF-8 -*- nums [-1, 0, 1,1, 2, -1, -4,0,2,1,-3,4,10,-9] def three_sum(nums):nums.sort()n len(nums)result []for i in range(n-2):# n-2,此时i取值到n-2-1,即倒数第3个数&…...
HttpServletRequest常用方法
方法说明示例String getMethod()获取请求的 HTTP 方法(如 GET、POST 等)。request.getMethod() 返回 "GET"String getRequestURI()获取请求的 URI(路径部分,不包括域名和协议)。请求 http://localhost:8080/…...

BugKu Web渗透之网站被hei(仅仅是ctf题目名称)
启动场景,打开网页,显示如下: 目前没有看出任何异常。 步骤一: 右键查看源代码。源代码较多,也没发现异常。 步骤二: 用dirsearch扫描网站目录。 如图: 看起来shell.php很可疑。 步骤三&…...
群论在现代密码学中的应用探索与实践 —— 从理论到C语言实现
1. 引言:数字时代的信息安全挑战 随着互联网和数字技术的快速发展,信息安全问题变得日益严峻。无论是个人隐私保护,还是企业数据安全,乃至国家安全,都依赖于有效的加密技术保障信息的机密性和完整性。网络攻击、数据泄…...
深入理解MySQL死锁:从原理、案例到解决方案
一、MySQL死锁的概念与定义 1. 死锁的基本定义 MySQL中的死锁是指两个或多个事务在同一资源上相互等待对方释放锁,导致这些事务都无法继续执行的情况。从本质上讲,死锁是多个事务形成了一个等待环路,每个事务都在等待另一个事务所持有的锁资…...

关于华为仓颉编程语言
文章目录 一、基本概况二、技术特点1. 多范式编程2. 原生智能化3. 高性能与安全4. 全场景兼容 三、编译器与开发工具四、语言相似性对比五、行业应用实例总结 最近经常看到这个东西,于是搜了一下,整理了一些内容,水一篇,以后慢慢研…...
无字母数字webshell的命令执行
在Web安全领域,WebShell是一种常见的攻击手段,通过它攻击者可以远程执行服务器上的命令,获取敏感信息或控制系统。而无字母数字WebShell则是其中一种特殊形式,通过避免使用字母和数字字符,来绕过某些安全机制的检测。 …...
Spring AI 项目实战(五):Spring Boot + AI + DeepSeek + Redis 实现聊天应用上下文记忆功能(附完整源码)
系列文章 序号文章名称1Spring AI 项目实战(一):Spring AI 核心模块入门2Spring AI 项目实战(二):Spring Boot + AI + DeepSeek 深度实战(附完整源码)3Spring AI 项目实战(三):Spring Boot + AI + DeepSeek 打造智能客服系统(附完整源码)4Spring AI 项目实战(四…...
【华为云Astro-服务编排】服务编排使用全攻略
目录 概述 为什么使用服务编排 服务编排基本能力 拖拉拽式编排流程 逻辑处理 对象处理 服务单元组合脚本、原生服务、BO、第三方服务 服务编排与模块间调用关系 脚本 对象 标准页面 BPM API接口 BO 连接器 如何创建服务编排 创建服务编排 如何开发服务编排 服…...

解决el-select选择框右侧下拉箭头遮挡文字问题
如图所示: el-select长度较短的时候,选择框右侧下拉箭头会遮挡选中的数据 选中数据被遮挡 解决办法: 组件如下: <td class"fmtd" :colspan"col.ptproCupNum" v-for"col in row" :key"…...

20250603在荣品的PRO-RK3566开发板的Android13下的使用命令行来查看RK3566的温度【显示优化版本】
20250603在荣品的PRO-RK3566开发板的Android13下的使用命令行来查看RK3566的温度【显示优化版本】 2025/6/3 11:58 RK3566的cpu运行效率 top busybox top rk3566_t:/ # rk3566_t:/ # rk3566_t:/ # cd /sys/class/thermal/ rk3566_t:/sys/class/thermal # ls -l rk3566_t:/sys/c…...

C语言字符数组初始化的5种方法(附带实例)
所谓初始化,就是在定义的同时进行赋值。 C语言中,初始化字符数组的方式多样,每种方式都有其特定的用途和优势。 1、使用字符串字面量初始化 最常见和简洁的初始化方式是使用字符串字面量。在这种方法中,我们直接将一个用双引号…...