SaToken认证授权快速上手

SaToken简介

SaToken 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。Sa-Token 旨在以简单、优雅的方式完成系统的权限认证部分。SaToken官网,原理如下
请添加图片描述

认证授权实现

1 创建5张测试基础表

利用经典RBAC理论,创建5张基础表,用于模拟用户的角色和权限功能。
users用户表
在这里插入图片描述
role角色表
在这里插入图片描述
role_users角色用户表
在这里插入图片描述
promission权限表
在这里插入图片描述
role_promission角色权限表
在这里插入图片描述

可以看到
用户1zhangsan拥有admin和guest角色,拥有user-read、user-write、product-read、product-read四个权限。
用户2拥有guest角色,拥有user-read、product-read两个权限。

2 配置文件

pom.xml引入依赖

        <!-- Sa-Token 权限认证,在线文档:https://sa-token.cc -->
        <dependency>
            <groupId>cn.dev33</groupId>
            <artifactId>sa-token-spring-boot-starter</artifactId>
            <version>1.38.0</version>
        </dependency>

application-dev.yml增加配置

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

3 Sa-Token的全局拦截器

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

4 自定义权限认证接口扩展

自定义接口实现SaToken框架的StpInterface接口,自动帮我们进行执行业务逻辑(获取权限集合,获取角色集合)

/**
 * 自定义权限认证接口扩展,Sa-Token 将从此实现类获取每个账号拥有的权限码
 * 只要实现了SaToken的StpInterface接口,
 * 并且加了@Component被SpringBoot管理,框架就会自动帮我们进行执行业务逻辑
 *
 * @author huahua
 * @since 2024/8/23
 */
@Component
public class StpInterfaceImpl implements StpInterface {

    @Resource
    private JdbcTemplate jdbcTemplate;

    // 权限认证校验SaCheckPermission,SaCheckRole注解,必须具有指定权限才能进入该方法。
    // 可以标注在方法、类上(效果等同于标注在此类的所有方法上)

    /**
     * 根据登录id和登录类型获取用户权限列表,返回一个账号所拥有的 权限 码集合
     * <p>
     * 该方法通过查询数据库,获取指定用户所拥有的所有权限代码
     * 查询涉及3张自定义报表:role_user角色用户关联表、role_promission角色权限关联表、promisssion权限表
     * 查询条件为用户id,连接3个表获取当前用户所有角色权限信息,从而提取权限代码
     *
     * @param loginId   用户登录id
     * @param loginType 登录类型
     * @return 权限列表
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        System.out.println("读取权限列表");
        List<String> list = new ArrayList<>();
        // 通过用户id查询此id对应的权限列表
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select distinct promission_code from role_users ru,role_promission rp,promission p" +
                " where ru.role_id = rp.role_id and rp.promission_id = p.permission_id and ru.user_id = ?", loginId);
        for (Map<String, Object> map : maps) {
            list.add(map.get("promission_code").toString());
        }
        return list;
    }

    /**
     * 根据登录id和登录类型获取用户权限列表,返回一个账号所拥有的 角色 码集合
     *
     * @param loginId   用户登录id
     * @param loginType 登录类型
     * @return 角色列表
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        List<String> list = new ArrayList<>();
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select distinct r.role_code from role_users ru,role r where ru.role_id = r.role_id and ru.user_id = ?", loginId);
        for (Map<String, Object> map : maps) {
            list.add(map.get("role_code").toString());
        }
        return list;
    }

}

5 SaToken用户控制层

/**
 * sa-token用户控制层
 *
 * @author huahua
 * @DATE 2024/8/23
 **/
@RestController
@RequestMapping("/user/")
public class UserController {
    @Resource
    private JdbcTemplate jdbcTemplate;

    // 测试登录,浏览器访问: http://localhost:8086/user/doLogin?username=lisi&password=lisi
    @RequestMapping("doLogin")
    public SaResult doLogin(String username, String password) {
        List<Map<String, Object>> list =
                jdbcTemplate.queryForList("select user_id from users where user_name = ? and password = ?", username, password);
        if (list.isEmpty()) {
            return SaResult.error("用户名或密码错误");
        } else {
            StpUtil.login(list.get(0).get("user_id"));
            return SaResult.ok("登录成功");
        }
    }

    // 查询登录状态,浏览器访问: http://localhost:8086/user/isLogin
    @RequestMapping("isLogin")
    public SaResult isLogin() {
        return SaResult.ok("是否登录:" + StpUtil.isLogin());
    }

    /**
     * 查询用户信息接口,需要具备自定义的‘user-query’权限
     *
     * @return SaResult 操作结果,返回成功状态
     */
    @SaCheckPermission("user-read")
    @GetMapping("findUsers")
    public SaResult findUsers() {
        return SaResult.ok();
    }

    /**
     * 创建用户的接口,需具备‘user-write’或'write'权限之一
     * SaMode.AND, 标注一组权限,会话必须全部具有才可通过校验。
     * SaMode.OR, 标注一组权限,会话只要具有其一即可通过校验。
     *
     * @return SaResult 操作结果,返回成功状态
     */
    @SaCheckPermission(value = {"user-write", "write"}, mode = SaMode.OR)
    @GetMapping("createUser")
    public SaResult createUser() {
        /*
        // 查询权限信息 ,如果当前会话未登录,会返回一个空集合
        List<String> permissionList = StpUtil.getPermissionList();
        System.out.println("当前登录账号拥有的所有权限:" + permissionList);

        // 查询角色信息 ,如果当前会话未登录,会返回一个空集合
        List<String> roleList = StpUtil.getRoleList();
        System.out.println("当前登录账号拥有的所有角色:" + roleList);
        */
        return SaResult.ok();
    }

    /**
     * 删除用户
     * 代表需要拥有角色 admin 才可以操作
     *
     * @return SaResult 操作结果,返回成功状态
     */
    @SaCheckRole("admin")
    @GetMapping("/deleteUser")
    public SaResult deleteUser(){
        return SaResult.ok();
    }
}

测试验证

用户2登录验证权限

发现用户2,没有deleteUser和createUser用户权限,因为SaCheckRole和SaCheckPermission框架注解帮我们做了权限管控!
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

用户1登录验证权限

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

项目代码结构

项目结构如下,源码demo-springboot-mybatisplus,欢迎star
在这里插入图片描述

  • 18
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值