-->

satoken实现登陆验证

1. 第一步 导入依赖

// Sa-Token 权限认证,在线文档:https://sa-token.cc
implementation 'cn.dev33:sa-token-spring-boot-starter:1.34.0'

2. 第二步 配置文件

server:
    # 端口
    port: 8081

############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token: 
    # token名称 (同时也是cookie名称)
    token-name: satoken
    # token有效期,单位s 默认30天, -1代表永不过期 
    timeout: 2592000
    # token临时有效期 (指定时间内无操作就视为token过期) 单位: 秒
    activity-timeout: -1
    # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) 
    is-concurrent: true
    # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) 
    is-share: true
    # token风格
    token-style: uuid
    # 是否输出操作日志 
    is-log: false

3. 第三步 Application启动类

如果想看一下satoken配置,可以在启动类中加入如下输出语句

System.out.println("启动成功:Sa-Token配置如下:" + SaManager.getConfig());

4. 登陆使用

登陆接口

    @PostMapping("/login")
    public ReturnResult Login(@RequestBody User user){
        User user_data = userService.Login(user.username,user.password);
        System.out.println("=========================="+ user_data);
        if(!Objects.equals(user_data,"")){
            StpUtil.login(user_data.id);
            return ReturnResult.buildSuccessResult(true);
        }else {
            return ReturnResult.buildFailureResult("登陆失败");
        }
    }

其中,StpUtil.login是可以直接放进User类的,但是会有警告,这里建议只存User.id

登陆校验

    @GetMapping()
    public ReturnResult getAllUser(){
        SaResult.ok("是否登录:" + StpUtil.isLogin());
        SaResult.ok("token:" + StpUtil.getTokenInfo());
        if (StpUtil.isLogin()){
            return ReturnResult.buildSuccessResult(userService.list());
        }
        else{
            return ReturnResult.buildFailureResult("尚未登陆");
        }
    }

StpUtil.isLogin()为检验当前satoken是否登陆

image

可以看到我的APIpost中已经携带了satoken

权限校验

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

获取权限列表:

package com.example.studydemo.modules.User;

import cn.dev33.satoken.stp.StpInterface;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义权限加载接口实现类
 */
@Component    // 保证此类被 SpringBoot 扫描,完成 Sa-Token 的自定义权限验证扩展
public class StpInterfaceImpl implements StpInterface {

    /**
     * 返回一个账号所拥有的权限码集合
     */
    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        // 本 list 仅做模拟,实际项目中要根据具体业务逻辑来查询权限
        List<String> list = new ArrayList<String>();
        list.add("101");
        list.add("user.add");
        list.add("user.update");
//        list.add("user.get");
        list.add("user.delete");
        list.add("art.*");
        return list;
    }

    /**
     * 返回一个账号所拥有的角色标识集合 (权限与角色可分开校验)
     */
    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        // 本 list 仅做模拟,实际项目中要根据具体业务逻辑来查询角色
        List<String> list = new ArrayList<String>();
        list.add("admin");
        list.add("super-admin");
        return list;
    }

}

上述的权限列表全是定死的,实际中应当从数据库获取权限列表

所涉及函数如下:

// 获取:当前账号所拥有的权限集合
StpUtil.getPermissionList();

// 判断:当前账号是否含有指定权限, 返回 true 或 false
StpUtil.hasPermission("user.add");        

// 校验:当前账号是否含有指定权限, 如果验证未通过,则抛出异常: NotPermissionException 
StpUtil.checkPermission("user.add");        

// 校验:当前账号是否含有指定权限 [指定多个,必须全部验证通过]
StpUtil.checkPermissionAnd("user.add", "user.delete", "user.get");        

// 校验:当前账号是否含有指定权限 [指定多个,只要其一验证通过即可]
StpUtil.checkPermissionOr("user.add", "user.delete", "user.get");    

Controller应用:

    @GetMapping("/{id}")
    public ReturnResult getById(@PathVariable Integer id){
        StpUtil.getPermissionList(StpUtil.getLoginId());
        if (StpUtil.hasPermission("user.get")){
            return ReturnResult.buildSuccessResult(userService.getById(id));
        } else {
            return ReturnResult.buildFailureResult("权限不足");
        }

    }

角色校验和上述类似,函数有所更改:

// 获取:当前账号所拥有的角色集合
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");  

5. satoken过程详解

image

上述为satoken登陆过程,我的理解是satoken为后端在登陆时给前端的一个证书,之后前端每次调用接口时,都要带着satoken的证书,否则无法访问,退出登录时将证书销毁就好,他不同于cookies只存在前端界面,也不同于session存储于后端,satoken是前端与后端交互的结果

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

Sa-Token 旨在以简单、优雅的方式完成系统的权限认证部分,以登录认证为例,你只需要:

// 会话登录,参数填登录人的账号id 
StpUtil.login(10001);

无需实现任何接口,无需创建任何配置文件,只需要这一句静态代码的调用,便可以完成会话登录认证。

如果一个接口需要登录后才能访问,我们只需调用以下代码:

// 校验当前客户端是否已经登录,如果未登录则抛出 `NotLoginException` 异常
StpUtil.checkLogin();

在 Sa-Token 中,大多数功能都可以一行代码解决:

踢人下线:

// 将账号id为 10077 的会话踢下线 
StpUtil.kickout(10077);

权限认证:

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

路由拦截鉴权:

// 根据路由划分模块,不同模块不同鉴权 
registry.addInterceptor(new SaInterceptor(handler -> {
    SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
    SaRouter.match("/admin/**", r -> StpUtil.checkPermission("admin"));
    SaRouter.match("/goods/**", r -> StpUtil.checkPermission("goods"));
    SaRouter.match("/orders/**", r -> StpUtil.checkPermission("orders"));
    SaRouter.match("/notice/**", r -> StpUtil.checkPermission("notice"));
    // 更多模块... 
})).addPathPatterns("/**");

当你受够 Shiro、SpringSecurity 等框架的三拜九叩之后,你就会明白,相对于这些传统老牌框架,Sa-Token 的 API 设计是多么的简单、优雅!


参考:satoken官网

posted @   ꧁ʚ星月天空ɞ꧂  阅读(647)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示