微服务网关SpringCloudGateway+SaToken鉴权

[复制链接]
发表于 2025-6-16 10:44:12 | 显示全部楼层 |阅读模式
目录

概念
前置知识回顾
拿到UserInfo 用于自定义权限和角色的获取逻辑
最后进行要进行 satoken 过滤器全局配置


概念

做权限认证的时候 我们首先要明确两点
我们必要的角色有几种 我们必要的权限有几种

角色 分两种
ADMIN 管理员 :可管理商品
CUSTIOMER 普通用户 :

权限 分四种
BASIC 根本权限 :可欣赏商品
AUTU 已实名认证权限 :可下单支付
FROZEN 被冻结用户权限
NONE 没有任何权限

前置知识回顾

在阅读完 sa-token 的文档
我发现原来权限验证云云简单
我们只必要 利用StpUtil即可
这个在开辟博客的时候写过相干的
  1. // 用户已存在,直接登录
  2. StpUtil.login(userInfo.getUserId(), new SaLoginModel().setIsLastingCookie(loginParam.getRememberMe())
  3.        .setTimeout(DEFAULT_LOGIN_SESSION_TIMEOUT));
  4. // 将用户信息存入会话
  5. StpUtil.getSession().set(userInfo.getUserId().toString(), userInfo);
  6. // 创建登录结果对象
  7. LoginVO loginVO = new LoginVO(userInfo);
  8. // 返回登录成功响应
  9. return Result.success(loginVO);
复制代码

拿到UserInfo 用于自定义权限和角色的获取逻辑

我们在用 StpUtil 去拿这个登录信息
进行校验
很容易明白 我们在登录模块 放入了一个 UserInfo 对象进去
包罗了用户了信息
  1. package cn.hollis.nft.turbo.api.user.response.data;
  2. import cn.hollis.nft.turbo.api.user.constant.UserRole;
  3. import cn.hollis.nft.turbo.api.user.constant.UserStateEnum;
  4. import com.github.houbb.sensitive.annotation.strategy.SensitiveStrategyPhone;
  5. import lombok.Getter;
  6. import lombok.NoArgsConstructor;
  7. import lombok.Setter;
  8. import java.util.Date;
  9. /**
  10. * @author Hollis
  11. */
  12. @Getter
  13. @Setter
  14. @NoArgsConstructor
  15. public class UserInfo extends BasicUserInfo {
  16.     private static final long serialVersionUID = 1L;
  17.     /**
  18.      * 手机号
  19.      */
  20.     @SensitiveStrategyPhone
  21.     private String telephone;
  22.     /**
  23.      * 状态
  24.      *
  25.      * @see UserStateEnum
  26.      */
  27.     private String state;
  28.     /**
  29.      * 区块链地址
  30.      */
  31.     private String blockChainUrl;
  32.     /**
  33.      * 区块链平台
  34.      */
  35.     private String blockChainPlatform;
  36.     /**
  37.      * 实名认证
  38.      */
  39.     private Boolean certification;
  40.     /**
  41.      * 用户角色
  42.      */
  43.     private UserRole userRole;
  44.     /**
  45.      * 邀请码
  46.      */
  47.     private String inviteCode;
  48.     /**
  49.      * 注册时间
  50.      */
  51.     private Date createTime;
  52.     public boolean userCanBuy() {
  53.         if (this.getUserRole() != null && !this.getUserRole().equals(UserRole.CUSTOMER)) {
  54.             return false;
  55.         }
  56.         // 判断买家状态
  57.         if (this.getState() != null && !this.getState().equals(UserStateEnum.ACTIVE.name())) {
  58.             return false;
  59.         }
  60.         // 判断买家状态
  61.         if (this.getState() != null && !this.getCertification()) {
  62.             return false;
  63.         }
  64.         return true;
  65.     }
  66. }
复制代码
我们sa-token 提供的接口中重写权限校验方法
实现stpInterface 调用处理这个接口方法
我们就是再把这个对象拿出来
  1. // 根据用户登录ID和登录类型返回不同的权限列表
  2. UserInfo userInfo = (UserInfo) StpUtil.getSessionByLoginId(loginId).get((String) loginId);
复制代码
然后找到权限 返回摆列值
摆列值要包装成 list 类型
这边返回的是List类型


这些文档里都有...
  1. package cn.hollis.nft.turbo.gateway.auth;
  2. import cn.dev33.satoken.stp.StpInterface;
  3. import cn.dev33.satoken.stp.StpUtil;
  4. import cn.hollis.nft.turbo.api.user.constant.UserPermission;
  5. import cn.hollis.nft.turbo.api.user.constant.UserRole;
  6. import cn.hollis.nft.turbo.api.user.constant.UserStateEnum;
  7. import cn.hollis.nft.turbo.api.user.response.data.UserInfo;
  8. import org.springframework.stereotype.Component;
  9. import java.util.List;
  10. /**
  11. * 自定义权限验证接口实现类
  12. * StpInterface 接口用于自定义权限和角色的获取逻辑。
  13. * StpInterfaceImpl 类实现了 StpInterface 接口,通过用户的会话信息动态获取用户的权限和角色列表。
  14. * 在 Sa - Token 框架进行权限验证时,会调用该类的方法来确定用户是否具备相应的权限和角色。
  15. * 注意:这边通过用户会话信息动态获取用户权限和角色列表
  16. *
  17. * @author Hollis
  18. */
  19. @Component
  20. public class StpInterfaceImpl implements StpInterface {
  21.     /**
  22.      * 根据用户的登录 ID 和登录类型获取用户的权限列表
  23.      *
  24.      * @param loginId  用户的登录 ID
  25.      * @param loginType 用户的登录类型
  26.      * @return 用户的权限列表,以字符串集合形式返回
  27.      */
  28.     @Override
  29.     public List<String> getPermissionList(Object loginId, String loginType) {
  30.         // 从会话中根据登录 ID 获取用户信息
  31.         UserInfo userInfo = (UserInfo) StpUtil.getSessionByLoginId(loginId).get((String) loginId);
  32.         // 如果用户角色是管理员,或者用户状态为激活状态、已认证状态
  33.         if (userInfo.getUserRole() == UserRole.ADMIN
  34.                 || userInfo.getState().equals(UserStateEnum.ACTIVE.name())
  35.                 || userInfo.getState().equals(UserStateEnum.AUTH.name()) ) {
  36.             // 赋予用户基础权限和认证权限
  37.             return List.of(UserPermission.BASIC.name(), UserPermission.AUTH.name());
  38.         }
  39.         // 如果用户状态为初始状态
  40.         if (userInfo.getState().equals(UserStateEnum.INIT.name())) {
  41.             // 赋予用户基础权限
  42.             return List.of(UserPermission.BASIC.name());
  43.         }
  44.         // 如果用户状态为冻结状态
  45.         if (userInfo.getState().equals(UserStateEnum.FROZEN.name())) {
  46.             // 赋予用户冻结权限
  47.             return List.of(UserPermission.FROZEN.name());
  48.         }
  49.         // 其他情况,赋予用户无权限
  50.         return List.of(UserPermission.NONE.name());
  51.     }
  52.     /**
  53.      * 根据用户的登录 ID 和登录类型获取用户的角色列表
  54.      *
  55.      * @param loginId  用户的登录 ID
  56.      * @param loginType 用户的登录类型
  57.      * @return 用户的角色列表,以字符串集合形式返回
  58.      */
  59.     @Override
  60.     public List<String> getRoleList(Object loginId, String loginType) {
  61.         // 从会话中根据登录 ID 获取用户信息
  62.         UserInfo userInfo = (UserInfo) StpUtil.getSessionByLoginId(loginId).get((String) loginId);
  63.         // 如果用户角色是管理员
  64.         if (userInfo.getUserRole() == UserRole.ADMIN) {
  65.             // 返回管理员角色
  66.             return List.of(UserRole.ADMIN.name());
  67.         }
  68.         // 其他情况,返回普通用户角色
  69.         return List.of(UserRole.CUSTOMER.name());
  70.     }
  71. }
复制代码
最后进行要进行 satoken 过滤器全局配置

SaReactorFilter

  1. package cn.hollis.nft.turbo.gateway.auth;
  2. import cn.dev33.satoken.exception.NotLoginException;
  3. import cn.dev33.satoken.exception.NotPermissionException;
  4. import cn.dev33.satoken.exception.NotRoleException;
  5. import cn.dev33.satoken.reactor.filter.SaReactorFilter;
  6. import cn.dev33.satoken.router.SaRouter;
  7. import cn.dev33.satoken.stp.StpUtil;
  8. import cn.dev33.satoken.util.SaResult;
  9. import cn.hollis.nft.turbo.api.user.constant.UserPermission;
  10. import cn.hollis.nft.turbo.api.user.constant.UserRole;
  11. import lombok.extern.slf4j.Slf4j;
  12. import org.springframework.context.annotation.Bean;
  13. import org.springframework.context.annotation.Configuration;
  14. /**
  15. * sa-token的全局配置类,用于配置鉴权过滤器和异常处理逻辑
  16. *
  17. * @author Hollis
  18. */
  19. @Configuration
  20. @Slf4j
  21. public class SaTokenConfigure {
  22.     /**
  23.      * 创建并配置 SaReactorFilter 实例,该过滤器用于对请求进行鉴权和异常处理
  24.      *
  25.      * @return 配置好的 SaReactorFilter 实例
  26.      */
  27.     @Bean
  28.     public SaReactorFilter getSaReactorFilter() {
  29.         return new SaReactorFilter()
  30.                 // 配置需要拦截的请求地址,/** 表示拦截所有请求
  31.                 .addInclude("/**")
  32.                 // 配置不需要拦截的请求地址,这里排除了网站图标请求
  33.                 .addExclude("/favicon.ico")
  34.                 // 设置鉴权方法,每次请求进入时会执行该方法进行鉴权
  35.                 .setAuth(obj -> {
  36.                     // 登录校验:拦截所有路由,但排除指定的开放路由,对其他请求进行登录状态检查
  37.                     SaRouter.match("/**").notMatch("/auth/**", "/collection/collectionList", "/collection/collectionInfo", "/wxPay/**").check(r -> StpUtil.checkLogin());
  38.                     // 权限认证:针对不同模块的请求,校验不同的权限
  39.                     // 管理界面请求需要用户具备管理员角色
  40.                     SaRouter.match("/admin/**", r -> StpUtil.checkRole(UserRole.ADMIN.name()));
  41.                     // 下单界面请求需要用户具备实名认证权限
  42.                     SaRouter.match("/trade/**", r -> StpUtil.checkPermission(UserPermission.AUTH.name()));
  43.                     // 用户界面请求需要用户具备基本权限或冻结权限
  44.                     SaRouter.match("/user/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(), UserPermission.FROZEN.name()));
  45.                     // 商品界面请求需要用户具备基本权限或冻结权限
  46.                     SaRouter.match("/order/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(),UserPermission.FROZEN.name()));
  47.                 })
  48.                 // 设置异常处理方法,当鉴权方法抛出异常时会进入该方法进行处理
  49.                 .setError(this::getSaResult);
  50.     }
  51.     /**
  52.      * 根据不同的异常类型,返回相应的错误信息
  53.      *
  54.      * @param throwable 捕获到的异常对象
  55.      * @return 封装了错误信息的 SaResult 对象
  56.      */
  57.     private SaResult getSaResult(Throwable throwable) {
  58.         switch (throwable) {
  59.             // 处理用户未登录异常
  60.             case NotLoginException notLoginException:
  61.                 // 记录错误日志日志
  62.                 log.error("请先登录");
  63.                 // 返回未登录的错误信息
  64.                 return SaResult.error("请先登录");
  65.             // 处理用户角色不匹配异常
  66.             case NotRoleException notRoleException:
  67.                 // 判断是否是管理员角色权限问题
  68.                 if (UserRole.ADMIN.name().equals(notRoleException.getRole())) {
  69.                     // 记录越权使用的错误日志日志
  70.                     log.error("请勿越权使用!");
  71.                     // 返回越权使用的错误信息
  72.                     return SaResult.error("请勿越权使用!");
  73.                 }
  74.                 // 记录无权限操作的错误日志日志
  75.                 log.error("您无权限进行此操作!");
  76.                 // 返回无权限操作的错误信息
  77.                 return SaResult.error("您无权限进行此操作!");
  78.             // 处理用户权限不足异常
  79.             case NotPermissionException notPermissionException:
  80.                 // 判断是否是实名认证权限问题
  81.                 if (UserPermission.AUTH.name().equals(notPermissionException.getPermission())) {
  82.                     // 记录需要实名认证的错误日志
  83.                     log.error("请先完成实名认证!");
  84.                     // 返回需要实名认证的错误信息
  85.                     return SaResult.error("请先完成实名认证!");
  86.                 }
  87.                 // 记录无权限操作的错误日志
  88.                 log.error("您无权限进行此操作!");
  89.                 // 返回无权限操作的错误信息
  90.                 return SaResult.error("您无权限进行此操作!");
  91.             // 处理其他未知异常
  92.             default:
  93.                 // 返回异常的错误信息
  94.                 return SaResult.error(throwable.getMessage());
  95.         }
  96.     }
  97. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

© 2001-2025 Discuz! Team. Powered by Discuz! X3.5

GMT+8, 2025-7-21 20:23 , Processed in 0.089438 second(s), 31 queries 手机版|qidao123.com技术社区-IT企服评测▪应用市场 ( 浙ICP备20004199 )|网站地图

快速回复 返回顶部 返回列表