当前位置: 首页 > backend >正文

微服务网关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());}}
}
http://www.xdnf.cn/news/12251.html

相关文章:

  • 当.txt无法打开,如何恢复成记事本
  • 2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版
  • Python数据可视化科技图表绘制系列教程(四)
  • 好得睐:以品质守味、以科技筑基,传递便捷与品质
  • C++中`printf`格式化输出的实用案例和说明
  • 【项目实践】SMBMS(Javaweb版)(三)登出、注册、注销、修改
  • 成工fpga(知识星球号)——精品来袭
  • Firefox 134.0.1 Win64 版详细安装指南
  • 一些实用的chrome扩展0x01
  • React从基础入门到高级实战:React 实战项目 - 项目一:在线待办事项应用
  • 解锁日事清任务自定义字段功能:创建类型、配置字段与应用场景
  • day34- 系统编程之 网络编程(TCP)
  • Linux网络——socket网络通信udp
  • Unknown key: ‘auto_activate_base‘解决
  • C++笔记-C++11(一)
  • DeepSeek 赋能智能养老:情感陪伴机器人的温暖革新
  • DevExpress WinForms v24.2 - 新增日程组件、电子表格组件功能扩展
  • 压敏电阻的选型都要考虑哪些因素?同时注意事项都有哪些?
  • Vehicle HAL(7)--how client connect to Vehicle HAL?
  • Spring事务失效-----十大常见场景及解决方案全解析
  • Git Svn
  • 图像测试点列表
  • 如何实现本地mqtt服务器和云端服务器同步?
  • 基于责任链模式进行订单参数的校验
  • Flink 高可用集群部署指南
  • NuxtJS入门指南:环境安装及报错解决
  • 【Redis】类型补充
  • Oracle-高频业务表的性能检查
  • Tailwind CSS 实战:基于 Kooboo 构建 AI 对话框页面(七):消息框交互功能添加
  • 复变函数中的对数函数及其MATLAB演示