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是否登陆
可以看到我的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过程详解
上述为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官网
分类:
Java编程学习
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通