sa-token快速上手
  zaXu3fhJ6zVU 2023年11月02日 35 0


最近项目中使用到了新的权限框架,整理一下,做个记录,也做分享,如有错误,请指正。


文章目录

  • sa-token介绍
  • 功能及优势
  • 登录认证
  • 权限认证
  • 鉴权
  • 注解鉴权
  • 注册拦截器
  • 路由鉴权
  • redis集成



sa-token快速上手_spring boot

sa-token介绍

以下是官网的介绍

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

功能及优势

多设备登录,单点登录,分布式session会话,微服务网关鉴权,记住我模式,二级认证,身份互换,账号封禁,多账号体系密码加密

相比于spring security,shiro,似乎是更简单了,shiro我个人几乎没有接触过,security之前有自己写过,相比之下,虽然security可能更适配spring,但security感觉略带繁琐,也可能是我接触的少,不过相比之下使用sa-token更快捷。因为我接入sa-token花费的时间更少。

登录认证

以下是官方示例代码,调用登录方法执行登录后,不会向前端发送token,因为StpUtil.login(id)利用cookie自动注入的特新实现了,但严格来说,还是需要手动设置token

// 会话登录:参数填写要登录的账号id,建议的数据类型:long | int | String, 不可以传入复杂类型,如:User、Admin 等等
StpUtil.login(Object id);  
StpUtil.login(123);  
StpUtil.login("admin");

假设业务逻辑为(简化):

1.校验用户名,密码

2.校验通过执行登录操作

public R doLogin (adminLoginBo bo, String ip) {
    if (bo.getUsername () == null) {
            return R.fail ("参数不能为空");
        }
    //查询用户信息
    HyAdminUser adminUser = adminUserDao.selectOne (new LambdaQueryWrapper<HyAdminUser> ().eq (HyAdminUser :: getUsername, bo.getUsername ()));
    //校验密码
if (Objects.equals (adminUser.getPassword (), bo.getPassword)) {
    //校验通过
    //调用sa-token的登录方法
            StpUtil.login (adminUser.getId ());
    //获取token并返回
            return R.ok (StpUtil.getTokenInfo ());
            }
            return R.fail ("登录失败");
        }
        return R.fail ("用户名或密码错误");

此时登录和使用数据库用户登录都以及实现了,注销登录同理。

权限认证

使用权限认证需要掌握RBAC技术,我使用的是粗粒度的权限控制,做的比较简单只控制到页面,所以没有设计权限码。

权限校验分为权限校验角色校验

我使用的是基于角色校验,在role表中,admin为最高权限,user为普通用户权限,在数据库数据关联正确的情况下,可以通过以下方法查询当前用户角色实现代码鉴权,但是这里不需要鉴权,而是配合鉴权实现自动校验角色,并配置sa-token拦截器作出不同处理,将鉴权逻辑于业务逻辑分离。

// 获取:当前账号所拥有的角色集合
StpUtil.getRoleList();

// 判断:当前账号是否拥有指定角色, 返回 true 或 false
StpUtil.hasRole("super-admin");        

// 校验:当前账号是否含有指定角色标识, 如果验证未通过,则抛出异常: NotRoleException
StpUtil.checkRole("super-admin");        

// 校验:当前账号是否含有指定角色标识 [指定多个,必须全部验证通过]
StpUtil.checkRoleAnd("super-admin", "shop-admin");        

// 校验:当前账号是否含有指定角色标识 [指定多个,只要其一验证通过即可] 
StpUtil.checkRoleOr("super-admin", "shop-admin");

鉴权

注解鉴权

  • @SaCheckLogin: 登录校验 —— 只有登录之后才能进入该方法。
  • @SaCheckRole("admin"): 角色校验 —— 必须具有指定角色标识才能进入该方法。
  • @SaCheckPermission("user:add"): 权限校验 —— 必须具有指定权限才能进入该方法。
  • @SaCheckSafe: 二级认证校验 —— 必须二级认证之后才能进入该方法。
  • @SaCheckBasic: HttpBasic校验 —— 只有通过 Basic 认证后才能进入该方法。
  • @SaIgnore:忽略校验 —— 表示被修饰的方法或类无需进行注解鉴权和路由拦截器鉴权。
  • @SaCheckDisable("comment"):账号服务封禁校验 —— 校验当前账号指定服务是否被封禁。

注册拦截器

新建配置类SaTokenConfigure.java,实现WebMvcConfigurer,添加@Configuration注解,保证此类被springboot启动类扫描到

/*代表当前路径下,/**代表多级路径

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
    // 注册 Sa-Token 拦截器,打开注解式鉴权功能 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册 Sa-Token 拦截器,打开注解式鉴权功能 
        registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");    
    }
}

然后就可以使用注解鉴权了,以下是官方案例

// 登录校验:只有登录之后才能进入该方法 
@SaCheckLogin                        
@RequestMapping("info")
public String info() {
    return "查询用户信息";
}

// 角色校验:必须具有指定角色才能进入该方法 
@SaCheckRole("super-admin")        
@RequestMapping("add")
public String add() {
    return "用户增加";
}

// 权限校验:必须具有指定权限才能进入该方法 
@SaCheckPermission("user-add")        
@RequestMapping("add")
public String add() {
    return "用户增加";
}

// 二级认证校验:必须二级认证之后才能进入该方法 
@SaCheckSafe()        
@RequestMapping("add")
public String add() {
    return "用户增加";
}

// Http Basic 校验:只有通过 Basic 认证后才能进入该方法 
@SaCheckBasic(account = "sa:123456")
@RequestMapping("add")
public String add() {
    return "用户增加";
}

// 校验当前账号是否被封禁 comment 服务,如果已被封禁会抛出异常,无法进入方法 
@SaCheckDisable("comment")                
@RequestMapping("send")
public String send() {
    return "查询用户信息";
}

路由鉴权

此时依旧需要对接口手动添加大量@SaCheckLogin 注解,依旧不方便,对配置类SaTokenConfigure.java,按照sa-token的提示稍加修改,排除掉登录接口,匹配带有api的路径,并拦截,拦截后校验是否登录,即可实现除登录外全部接口的登录校验,代码如下:

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
    // 注册 Sa-Token 拦截器,打开注解式鉴权功能 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 注册 Sa-Token 拦截器,打开注解式鉴权功能 
                registry.addInterceptor (new SaInterceptor (handler -> {
            // 指定一条 match 规则
            SaRouter
                    .match ("/api/**")    // 拦截的 path 列表,可以写多个 */
                    .notMatch ("/api/login/doLogin")        // 排除掉的 path 列表,可以写多个
                    .check (r -> StpUtil.checkLogin ());        // 要执行的校验动作,可以写完整的 lambda 表达式
        })).addPathPatterns ("/**");   
    }
}

SaRouter.match() 匹配函数有两个参数:

  • 参数一:要匹配的path路由。
  • 参数二:要执行的校验函数。

在校验函数内不只可以使用 StpUtil.checkPermission("xxx") 进行权限校验,你还可以写任意代码

redis集成

sa-token默认将数据存储在内存中,速度快,避免了序列化和反序列化,但是也有缺点:

1.重启后数据会丢失

2.无法在分布式环境中共享数据

所以需要引入redis来做存储

除了需要引入redis依赖以外,还需要引入sa-token的两个依赖

提供redis实例化方案

<!-- 提供Redis连接池 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

集成redis方案

分为jdk默认序列化和jackson序列化方式两种,对应不同的依赖

jdk序列化依赖

<!-- Sa-Token 整合 Redis (使用 jdk 默认序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis</artifactId>
    <version>1.37.0</version>
</dependency>

jackson序列化依赖

<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis-jackson</artifactId>
    <version>1.37.0</version>
</dependency>

ncy>

**jackson序列化依赖**

```xml
<!-- Sa-Token 整合 Redis (使用 jackson 序列化方式) -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis-jackson</artifactId>
    <version>1.37.0</version>
</dependency>

引入redis依赖后只需要配置好redis的连接信息,sa-token可以自动实现登录数据保存。


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
zaXu3fhJ6zVU