一、Sa-Token 简介
Sa-Token 是一个轻量级 Java 权限认证框架,主要解决登录认证、权限认证、单点登录、OAuth2.0、分布式 Session 会话等一系列与权限相关的问题。相比于 Shiro 和 Spring Security,Sa-Token 具有以下特点:
- 简单易用:API 设计直观,学习成本低
- 功能全面:覆盖大部分认证授权场景
- 轻量高效:不依赖复杂设计,性能优异
- 模块化设计:可按需引入功能模块
- 良好扩展性:支持自定义各种组件
二、核心概念
1. 登录认证流程
用户登录 -> 生成Token -> 存储Token -> 返回给客户端
客户端携带Token -> 服务器验证Token -> 访问受保护资源
2. 核心组件
- StpUtil:核心工具类,提供登录、注销、权限校验等操作
- SaTokenConfig:配置类,可自定义各种参数
- SaInterceptor:拦截器,实现路由拦截鉴权
- SaTokenDao:Token 持久层接口,默认内存实现,可扩展为 Redis
3. 主要功能
- 登录认证
- 权限认证(角色/权限)
- Session 管理
- 踢人下线
- 多账号体系
- 单点登录
- 模拟他人账号
- 临时身份切换
三、Spring Boot 集成实战
1. 添加依赖
<!-- Sa-Token 核心包 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>最新版本</version>
</dependency>
<!-- 如果使用Redis持久化 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dao-redis</artifactId>
<version>最新版本</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2. 基础配置
# application.yml
sa-token:
# token名称 (同时也是cookie名称)
token-name: satoken
# token有效期,单位s 默认30天
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: true
3. 登录认证实现
@RestController
@RequestMapping("/user/")
public class UserController {
@PostMapping("doLogin")
public SaResult doLogin(String username, String password) {
// 模拟数据库校验
if("admin".equals(username) && "123456".equals(password)) {
// 登录成功,生成Token
StpUtil.login(10001);
return SaResult.ok("登录成功").setData(StpUtil.getTokenInfo());
}
return SaResult.error("登录失败");
}
// 查询登录状态
@GetMapping("isLogin")
public SaResult isLogin() {
return SaResult.ok("是否登录:" + StpUtil.isLogin());
}
// 退出登录
@GetMapping("logout")
public SaResult logout() {
StpUtil.logout();
return SaResult.ok();
}
}
4. 权限认证实现
@RestController
@RequestMapping("/admin/")
public class AdminController {
// 权限校验:必须具有admin权限才能进入
@SaCheckPermission("admin")
@GetMapping("menu")
public SaResult menu() {
return SaResult.data("管理员菜单");
}
// 角色校验:必须具有super-admin角色才能进入
@SaCheckRole("super-admin")
@GetMapping("settings")
public SaResult settings() {
return SaResult.data("系统设置");
}
// 二级认证:必须输入密码进行二次验证后才能进入
@SaCheckSafe()
@GetMapping("criticalOperation")
public SaResult criticalOperation() {
return SaResult.data("关键操作");
}
}
5. 全局拦截器配置
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
// 注册Sa-Token的注解拦截器,打开注解式鉴权功能
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册注解拦截器
registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
}
}
四、进阶功能
1. Redis 集成(分布式会话)
# application.yml
spring:
redis:
host: 127.0.0.1
port: 6379
password:
database: 0
sa-token:
# 配置Token持久化到Redis
is-share: true
is-read-body: false
is-read-head: true
is-v: false
token-prefix: "satoken:"
jwt-secret-key: null
id-token-timeout: 86400
dao: "redis"
2. 自定义会话管理
@Component
public class CustomSaTokenDao extends SaTokenDaoDefaultImpl {
// 重写数据访问层方法,例如使用MongoDB存储
@Override
public String get(String key) {
// 自定义实现
return super.get(key);
}
@Override
public void set(String key, String value, long timeout) {
// 自定义实现
super.set(key, value, timeout);
}
}
3. 注解鉴权
Sa-Token 提供丰富的注解用于权限控制:
@SaCheckLogin
: 登录校验@SaCheckRole("admin")
: 角色校验@SaCheckPermission("user:add")
: 权限校验@SaCheckSafe
: 二级认证校验@SaCheckBasic
: HttpBasic校验
4. 路由拦截鉴权
@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SaInterceptor(handler -> {
// 登录校验 -- 拦截所有路由
SaRouter.match("/**").check(r -> StpUtil.checkLogin());
// 角色校验 -- 拦截以 admin 开头的路由
SaRouter.match("/admin/**").check(r -> StpUtil.checkRole("admin"));
// 权限校验 -- 不同模块校验不同权限
SaRouter.match("/user/**", r -> StpUtil.checkPermission("user"));
SaRouter.match("/order/**", r -> StpUtil.checkPermission("order"));
})).addPathPatterns("/**");
}
}
五、最佳实践
-
Token 安全
- 使用 HTTPS
- 设置合理的 token 有效期
- 避免 token 在 URL 中传输
- 实现 token 续期机制
-
权限设计
- 遵循最小权限原则
- 使用 RBAC (基于角色的访问控制) 模型
- 实现权限缓存机制
-
性能优化
- 对于分布式系统使用 Redis 存储 token
- 合理设置 token 的过期时间
- 实现本地缓存减少持久层访问
-
监控与日志
- 记录关键认证操作
- 监控异常登录行为
- 实现登录设备管理
六、常见问题解决方案
-
Token 失效问题
- 检查 token 过期时间设置
- 验证 token 持久化是否正常工作
- 检查是否有并发登录冲突
-
跨域问题
@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*") .exposedHeaders("satoken"); // 重点暴露satoken头 } }
-
自定义响应格式
@RestControllerAdvice public class GlobalExceptionHandler { // 拦截所有未处理的SaToken异常 @ExceptionHandler(SaTokenException.class) public SaResult handlerSaTokenException(SaTokenException e) { return SaResult.error(e.getMessage()); } }
-
多账号体系
// 对于不同的账号体系,可以使用不同的StpUtil StpUtil.stpLogic("user").login(10001); // 用户体系登录 StpUtil.stpLogic("admin").login(1); // 管理员体系登录
七、总结
Sa-Token 作为一个轻量级的权限认证框架,通过简单的 API 设计和丰富的功能,能够满足大多数应用的认证授权需求。与 Spring Boot 的集成非常简便,通过少量配置即可实现强大的权限控制功能。
相比传统的 Shiro 和 Spring Security,Sa-Token 的学习曲线更为平缓,且针对常见场景提供了开箱即用的解决方案。特别是对于中小型项目,Sa-Token 能够显著降低权限系统的开发成本。
在实际项目中,建议根据业务需求选择合适的持久化方案(内存或 Redis),合理设计权限模型,并遵循安全最佳实践,以构建安全可靠的认证授权系统。