首页 > 其他分享 >Sa-Token介绍与SpringBoot环境下使用

Sa-Token介绍与SpringBoot环境下使用

时间:2024-01-18 09:02:31浏览次数:20  
标签:return SpringBoot 登录 class token 鉴权 Token Sa public

个人博客:无奈何杨(wnhyang)

个人语雀:wnhyang

共享语雀:在线知识共享

Github:wnhyang - Overview


官网:Sa-Token

一个轻量级 Java 权限认证框架,让鉴权变得简单、优雅!

介绍

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证权限认证单点登录OAuth2.0分布式Session会话微服务网关鉴权 等一系列权限相关问题。

官方文档写的已经非常好了。引用官方文档开头的一段话:

本文档将会尽力讲解每个功能的设计原因、应用场景,用心阅读文档,你学习到的将不止是 Sa-Token 框架本身,更是绝大多数场景下权限设计的最佳实践。

确实,通过阅读官方文档有学到很多东西,收获更大的是结合我的使用体验,下载并阅读源码后有学到了一些东西想和大家分享!这篇文章只是开头。

使用

1、准备工作

环境:

Spring Boot2.7.3

Sa-Token1.37.0

2、配置文件

关于sa-token的配置文件如下

############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token:
  # token 名称(同时也是 cookie 名称)
  token-name: Authorization
  # token 有效期(单位:秒) 默认30天,-1 代表永久有效
  timeout: 3600
  # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
  active-timeout: 1800
  # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
  is-concurrent: false
  # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
  is-share: true
  # 是否尝试从header里读取token
  is-read-header: true
  # 是否尝试从cookie里读取token
  is-read-cookie: false
  # token前缀
  token-prefix: "Bearer"
  # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
  token-style: tik
  # 是否输出操作日志
  is-log: true

3、自定义权限认证

官方文档:因为每个项目的需求不同,其权限设计也千变万化,因此 [ 获取当前账号权限码集合 ] 这一操作不可能内置到框架中, 所以 Sa-Token 将此操作以接口的方式暴露给你,以方便你根据自己的业务逻辑进行重写。

所以根据自己的不同业务设计需要的权限认证方法就好。下面是我项目中的写法,仅供参考。

@Setter
public class StpInterfaceImpl implements StpInterface {

    /**
     * 登录服务
     */
    private LoginService loginService;

    /**
     * 返回指定账号id所拥有的权限码集合
     *
     * @param loginId   账号id
     * @param loginType 账号类型
     * @return 该账号id具有的权限码集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        Login loginUser = loginService.getLoginUser();
        UserTypeEnum userType = UserTypeEnum.valueOf(loginUser.getType());
        if (userType == UserTypeEnum.PC) {
            return new ArrayList<>(loginUser.getPermissions());
        }

        return new ArrayList<>();
    }

    /**
     * 返回指定账号id所拥有的角色标识集合
     *
     * @param loginId   账号id
     * @param loginType 账号类型
     * @return 该账号id具有的角色标识集合
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        Login loginUser = loginService.getLoginUser();
        UserTypeEnum userType = UserTypeEnum.valueOf(loginUser.getType());
        if (userType == UserTypeEnum.PC) {
            return new ArrayList<>(loginUser.getRoleValues());
        }

        return new ArrayList<>();
    }
}

接着注册StpInterfaceImpl

@Configuration
public class SaTokenConfiguration {

    @Bean
    public LoginService loginService() {
        return new LoginServiceImpl();
    }

    @Bean
    public StpInterface stpInterface(LoginService loginService) {
        StpInterfaceImpl stpInterface = new StpInterfaceImpl();
        stpInterface.setLoginService(loginService);
        return stpInterface;
    }
}

4、Controller

4.1、工具类鉴权

satoken提供了StpUtill鉴权工具类,其中包含非常多的静态方法可以使用,详情请参考:Sa-Token

// 会话登录,参数填登录人的账号id 
StpUtil.login(10001);
// 校验当前客户端是否已经登录,如果未登录则抛出 `NotLoginException` 异常
StpUtil.checkLogin();
// 将账号id为 10077 的会话踢下线 
StpUtil.kickout(10077);

4.2、注解鉴权

尽管StpUtill鉴权工具类已经非常方便但还是有同学钟爱注解鉴权,satoken也是提供了这种方式的。

// 注解鉴权:只有具备 `user:add` 权限的会话才可以进入方法
@SaCheckPermission("user:add")
public String insert(SysUser user) {
    // ... 
    return "用户增加";
}

注解鉴权默认是关闭的,要使用的话需要将satoken全局拦截器注入到项目中!

@Configuration
public class SecurityConfiguration implements WebMvcConfigurer {

    /**
     * 注册sa-token的拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册路由拦截器,自定义验证规则
        registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
    }
}

如上就注册了satoken的全局拦截器,就可以愉快的使用注解权限了。官方文档:Sa-Token

注意:这里配置的是“/**”,也就是全路径,所有后面要在不需要鉴权的接口上加上@SaIgnore用于忽略鉴权。

如下配置了/auth开头的接口不用鉴权

@RestController
@RequiredArgsConstructor
@Validated
@RequestMapping("/auth")
@SaIgnore
public class AuthController {

    private final AuthService authService;

    /**
     * 登录
     *
     * @param reqVO 登录请求
     * @return token
     */
    @PostMapping("/login")
    public CommonResult<LoginRespVO> login(@RequestBody @Valid LoginReqVO reqVO) {
        return success(authService.login(reqVO));
    }

    ...
}

如下是一个简单的需要鉴权的示例

@RestController
@RequestMapping("/system/role")
@RequiredArgsConstructor
public class RoleController {

    private final RoleService roleService;

    /**
     * 创建角色
     *
     * @param reqVO 角色信息
     * @return id
     */
    @PostMapping("/create")
    @SaCheckPermission("system:role:create")
    public CommonResult<Long> createRole(@Valid @RequestBody RoleCreateReqVO reqVO) {
        return success(roleService.createRole(reqVO));
    }

    /**
     * 更新角色
     *
     * @param reqVO 角色信息
     * @return 结果
     */
    @PutMapping("/update")
    @SaCheckPermission("system:role:update")
    public CommonResult<Boolean> updateRole(@Valid @RequestBody RoleUpdateReqVO reqVO) {
        roleService.updateRole(reqVO);
        return success(true);
    }

    ...
}

5、全局异常

通过定义全局异常拦截器可以返回前端统一的格式,以下仅供参考。

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 权限码异常
     */
    @ExceptionHandler(NotPermissionException.class)
    public CommonResult<Void> handleNotPermissionException(NotPermissionException e, HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        log.error("请求地址'{}',权限码校验失败'{}'", requestUri, e.getMessage());
        return CommonResult.error(FORBIDDEN);
    }

    /**
     * 角色权限异常
     */
    @ExceptionHandler(NotRoleException.class)
    public CommonResult<Void> handleNotRoleException(NotRoleException e, HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        log.error("请求地址'{}',角色权限校验失败'{}'", requestUri, e.getMessage());
        return CommonResult.error(FORBIDDEN);
    }

    /**
     * 认证失败
     */
    @ExceptionHandler(NotLoginException.class)
    public CommonResult<Void> handleNotLoginException(NotLoginException e, HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        log.error("请求地址'{}',认证失败'{}',无法访问系统资源", requestUri, e.getMessage());
        return CommonResult.error(UNAUTHORIZED);
    }

    /**
     * 无效认证
     */
    @ExceptionHandler(SameTokenInvalidException.class)
    public CommonResult<Void> handleSameTokenInvalidException(SameTokenInvalidException e, HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        log.error("请求地址'{}',内网认证失败'{}',无法访问系统资源", requestUri, e.getMessage());
        return CommonResult.error(UNAUTHORIZED);
    }

    ...

}

6、跨域(可选)

官网也有提供解决方法Sa-Token,我非常建议你看完这篇文章后再决定使用什么方式Sa-Token

看个人选择吧,我这里使用的是satoken拦截器+普通corsFilter的方式。

@Configuration
public class OkayWebAutoConfiguration implements WebMvcConfigurer {

    /**
     * 跨域配置
     */
    @Bean
    public CorsFilter corsFilter()
    {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        // 设置访问源地址
        config.addAllowedOriginPattern("*");
        // 设置访问源请求头
        config.addAllowedHeader("*");
        // 设置访问源请求方法
        config.addAllowedMethod("*");
        // 有效期 1800秒
        config.setMaxAge(1800L);
        // 添加映射路径,拦截一切请求
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        // 返回新的CorsFilter
        return new CorsFilter(source);
    }

}

7、启动类

启动类确保以上需要的组件被扫描注册就好。

@SpringBootApplication
public class AdminApplication {

    public static void main(String[] args) {
        SpringApplication.run(AdminApplication.class, args);
    }
}

8、启动测试

这里我使用了redis,可以先忽略。

因为我的前端是一整个项目,不好拆出来贴代码,所以直接展示登录结果了!

尝试登录

发起一个创建请求,因为前端项目已经配置了发请求的header,所以请求就会带上前面的token了。

然后satoken拦截器发挥作用进行鉴权,关于拦截器如何鉴权的,我之后还会再讲的。这次先到这吧。


个人博客:无奈何杨(wnhyang)

个人语雀:wnhyang

共享语雀:在线知识共享

Github:wnhyang - Overview

标签:return,SpringBoot,登录,class,token,鉴权,Token,Sa,public
From: https://www.cnblogs.com/wnhyang/p/17971710

相关文章

  • 【学习笔记】后缀自动机 SAM
    一.后缀自动机的定义SAM(SuffixAutomaton)是一种有限状态自动机,仅可以接受一个字符串的所有后缀。如果您不懂自动机,那么换句话说:SAM是一个有向无环图。称每个结点为状态,边为状态间的转移,每个转移标有一个字母,同一节点引出的转移不同。SAM存在一个源点\(S\),称为初始状态......
  • 0.o?让我看看怎么个事儿之SpringBoot自动配置
    学习SpringBoot自动配置之前我们需要一些前置知识点:Java注解,看完就会用学会@ConfigurationProperties月薪过三千不是银趴~是@Import!@Conditional+@Configuration有没有搞头?首先我们提出2个问题:SpringBoot是干什么的?是用来简化Spring原生的复杂的xml配置的进阶框架......
  • SpringBoot+MybatisPlus+dynamic-datasources实现连接Postgresql和mysql多数据源
    场景dynamic-datasource-spring-boot-starter实现动态数据源Mysql和Sqlserver:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/117356693SpringBoot中整合MybatisPlus快速实现Mysql增删改查和条件构造器:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/detail......
  • Salesforce生成式AI聊天机器人「Einstein Copilot」,将于2月发布!
    Spring'24宣布,期待已久的EinsteinCopilot将于2024年2月落地Salesforce。该生成式AI聊天机器人将用于整个Salesforce产品套件,帮助企业做出更明智的决策,从而改善客户体验。EinsteinCopilot应用于CRM应用程序中,智能回应任何用户查询。甚至可以从整个生态系统中收集个性化数据,根......
  • 在 SAP Web IDE 个人版中根据模板创建项目时,选择 OData 服务时出现catalog service is
     1.NOTE2684697 ,重点是点2点5的问题 2.去掉CatalogServiceVersion2的系统别名(包括LOCAL)翻阅其他博客,有人说是因为系统别名,我给去掉了。 ......
  • 商业应用算力全球新标杆!浪潮信息八路服务器创SAP SD评测最高性能
    1月15日,据全球领先的企业应用软件提供商SAP发布的最新SAPSD评测结果,浪潮信息TS860G7服务器创下1,659,970 SAPS的最高性能成绩,成为商业应用算力的全球新标杆。TS860G7是浪潮信息最新一代的企业级八路服务器,其取得的最新成绩也成功超越了16路小型机系统保持的性能纪录。SAPSD是SAP......
  • 尚无忧【无人共享空间 saas 系统源码】无人共享麻将室系统源码共享自习室系统源码,共享
    可saas多开,非常方便,大大降低了上线成本UNIAPP+thinkphp+mysql独立开源!1、定位功能:可定位附近是否有店2、能通过关键字搜索现有的店铺3、个性轮播图展示,系统公告消息提醒4、个性化功能展示,智能排序,距离、价格排序5、现有店铺清单展示,订房可查看房间单价,根据日期、时间端订房,选择时......
  • ESAE Red Forest
     EnhancedSecurityAdministrativeEnvironment(ESAE)是一种安全管理架构,旨在加强组织的网络安全和信息安全。它通常用于大型企业和政府机构,以确保其计算机系统和网络受到适当的保护,防止未经授权的访问和数据泄露。ESAE的核心理念是将管理员和普通用户分隔开来,以降低潜在的......
  • SpringBoot中整合MybatisPlus快速实现Mysql增删改查和条件构造器
    场景Mybatis-Plus(简称MP)是一个Mybatis的增强工具,只是在Mybatis的基础上做了增强却不做改变,MyBatis-Plus支持所有Mybatis原生的特性,所以引入Mybatis-Plus不会对现有的Mybatis构架产生任何影响。MyBatis增强工具包,简化CRUD操作。启动加载XML配置时注入单表SQL操作,为简......
  • 你真的了解token续期嘛?
    SpringBoot+Vue中的Token续签机制在现代的全栈应用开发中,SpringBoot作为后端框架和Vue.js作为前端框架的组合非常流行。在这种架构中实现Token续签是保障应用安全的关键部分。本文旨在提供一个基于SpringBoot和Vue的长短Token续签示例。1.SpringBoot后端1.1长Token的生......