Sa-Token和Spring Security对比

前言

Sa-Token在中文社区迅速崛起,GitHub上已经积累了超过46K Stars

越来越多的Java项目开始从Spring Security、Shiro迁移到Sa-Token。

2026年3月,Sa-Token v1.45.0正式发布,全面适配Spring Boot 4,并新增了Jackson3插件等能力。

一、为什么我们需要权限框架?

在聊Sa-Token之前,我们先理解一个根本问题------为什么不能自己手写权限控制,非要用框架?

想象一下,你要为一个电商系统实现权限控制,手写代码大概长这样:

java 复制代码
public void updateProduct(Long productId, ProductDTO dto) {
    // 1. 检查用户是否登录
    User user = getCurrentUser();
    if (user == null) {
        throw new UnauthorizedException("请先登录");
    }
    // 2. 检查用户是否有编辑权限
    if (!user.hasPermission("product:update")) {
        throw new ForbiddenException("没有操作权限");
    }
    // 3. 检查是否是自己的商品
    Product product = productService.getById(productId);
    if (!product.getOwnerId().equals(user.getId())) {
        throw new ForbiddenException("只能修改自己的商品");
    }
    // 4. 实际业务逻辑
    productService.update(productId, dto);
}

看到问题了吗?

  • 每个方法都要重复写登录检查

  • 每个方法都要重复写权限校验

  • 每个方法都要自己管理Session/Token

  • 密码加密、CSRF防护要自己实现

  • 审计日志、安全事件处理要自己写

安全逻辑像"幽灵代码"一样渗透到业务代码的每个角落。

权限框架的价值,就是把这些问题抽象化、标准化、自动化

而Sa-Token,就是把这些事情做到极致的那一个。

二、一张图看懂Sa-Token的整体架构

在深入代码之前,我们先建立一个整体认知。

Sa-Token采用分层架构设计 ,将核心功能划分为认证层、权限层、存储层和扩展层四个层次,各层之间通过接口解耦。

这种分层架构的核心价值在于:每一层都可以被替换

你不想用内存存储?

换成Redis。

不想用默认的Token生成策略?

自己实现一个。

框架把控制权彻底交给了开发者。

三、核心-插件-适配器模型

Sa-Token最精妙的设计,是它基于核心-插件-适配器(Core-Plugin-Adapter)模型构建的整个框架。

核心层(sa-token-core) 是整个框架的心脏,零外部依赖,只包含最纯粹的认证逻辑、Session模型和SPI接口定义。这意味着它可以在任何Java环境中运行,不绑定任何Web框架。

插件层(sa-token-plugin) 提供了所有可插拔的功能扩展------Redis存储、JWT、SSO、OAuth2.0等。你只需要引入你需要的插件,不需要的绝不拖进来。

适配层(sa-token-starter) 负责将核心逻辑桥接到具体的Web框架------Spring Boot、Spring WebFlux、Solon、JFinal等。

3.1 SaManager:全局组件注册中心

SaManager是整个框架的中央注册表,持有所有全局组件的静态引用。

无论是存储层、策略层还是上下文处理器,都通过SaManager进行统一管理。

3.2 SaStrategy:策略模式的核心

SaStrategy是一个单例,允许开发者在不修改核心代码的情况下,覆盖内部算法

比如:

策略函数 默认行为 你可以替换成
createToken 生成UUID随机字符串 自定义Token格式
createSession 返回SaSession实例 自定义Session实现
routeMatcher 由Starter实现 自定义路由匹配规则
createStpLogic 返回默认StpLogic 多账号体系隔离

这种设计让框架的每一个核心行为都可以被替换,同时保持了核心代码的纯净和稳定。

四、登录认证的完整链路

这是Sa-Token最核心的功能。我们逐层拆解,看看StpUtil.login(10001)这一行代码背后到底发生了什么。

4.1 登录流程全景图

4.2 登录前的安全校验

进入StpLogic.login()方法后,首先执行的是账号封禁检查

复制代码
// 封禁key的拼接规则:satoken:login:disable:loginType:loginId
String disableKey = splicingKeyLoginDisable(loginId);
if (SaManager.getSaTokenDao().get(disableKey) != null) {
    throw new DisableLoginException("账号已被封禁");
}

这意味着,如果一个账号被管理员封禁了,任何登录尝试都会被在框架层面直接拦截,业务代码完全不需要关心。

4.3 Token的生成与存储

通过安全校验后,框架开始生成Token:

java 复制代码
// 简化版Token生成
public static String generateAccessToken(long loginId) {
    // 1. 生成随机字符串作为token主体
    String token = IdUtil.simpleUUID();
    // 2. 构建token信息对象
    SaTokenInfo tokenInfo = new SaTokenInfo()
        .setLoginId(loginId)
        .setToken(token)
        .setCreateTime(System.currentTimeMillis())
        .setExpireTime(System.currentTimeMillis() + StpLogic.getTokenTimeout());
    // 3. 存储token信息
    SaTokenDaoFactory.getDao().setTokenInfo(token, tokenInfo);
    return token;
}

这里有一个关键设计:Token的存储是可插拔的

默认存在内存里,但你可以轻松切换到Redis,实现分布式会话共享。

4.4 写入当前上下文

生成Token后,框架需要把Token注入到当前请求的上下文中:

java 复制代码
public void setTokenValue(String tokenValue, int cookieTimeout) {
    SaTokenConfig config = getConfig();
    SaStorage storage = SaHolder.getStorage();
    String tokenPrefix = config.getTokenPrefix();
    if (SaFoxUtil.isEmpty(tokenPrefix)) {
        storage.set(splicingKeyJustCreatedSave(), tokenValue);
    } else {
        storage.set(splicingKeyJustCreatedSave(), tokenPrefix + " " + tokenValue);
    }
    // 注入Cookie(自动)
    SaHolder.getResponse().addCookie(...);
}

你完全不需要手动操作Cookie或Header

Sa-Token利用Cookie自动注入的特性,让前端感应不到Token的存在,却能在下次请求时自动带上凭证。

4.5 多账号体系的隔离

在实际项目中,一个系统往往需要多套独立的认证体系------普通用户、管理员、API调用方等。

RuoYi-Vue-Plus通过自定义StpLogic子类实现了这种隔离:

java 复制代码
public class StpAdminUtil {
    // 管理员专属的StpLogic实例
    public static final StpLogic stpLogic = new StpLogic("admin") {
        @Override
        public String splicingKeyTokenValue(String tokenValue) {
            return "admin:" + tokenValue;  // Key前缀隔离
        }
    };
}

这种设计使得同一个系统可以同时存在多个互不干扰的认证域,每个域有独立的Token命名空间和会话管理。

五、分布式会话

有些小伙伴在工作中可能会遇到这个问题:单机跑得好好的,一上集群就出事了------登录态丢失、频繁掉线、会话不一致。

Sa-Token默认把会话数据存放在JVM内存中。

单机开发时,读写速度飞快,没有任何序列化/反序列化损耗。

但一旦应用重启,所有会话数据全部丢失。

在集群部署环境中,每个节点都有自己的内存,用户的登录请求落在节点A,下次请求落在节点B,节点B找不到会话,直接返回401。

5.1 分布式架构图

解决方案:接入Redis

XML 复制代码
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-redis</artifactId>
    <version>1.45.0</version>
</dependency>

配置完成后的效果:

  • 登录态多节点共享:用户在任意节点登录,所有节点都能识别

  • 水平扩展能力:增加节点不影响会话一致性

  • 重启不丢数据:应用重启,Redis里的会话依然有效

六、Sa-Token vs Spring Security对比

对比维度 Sa-Token Spring Security
核心定位 轻量级权限认证框架 企业级全面的安全解决方案
学习曲线 极低 ------StpUtil.login()即可上手 ------需理解过滤器链和SecurityContextHolder
架构模式 Core-Plugin-Adapter 过滤器链+SecurityContextHolder
侵入性 ------静态工具类,随处调用 ------需继承/实现类
配置方式 零配置启动 大量配置类
功能边界 聚焦高频认证场景 瑞士军刀,功能全面
分布式会话 原生支持Redis扩展 需Spring Session等组件

Spring Security的强大源于其深度集成与高度可定制性,但这也带来了著名的"学习曲线陡峭"问题。

新手开发者常常会陷入"我只是想加个登录,为什么需要理解整个过滤器链和SecurityContextHolder"的困惑中。

相比之下,Sa-Token的设计哲学是**"让安全变得简单"**。

它的核心API设计得非常直观------登录、注销、权限检查,几乎一行代码搞定。

一句话总结:Spring Security是"安全领域的瑞士军刀",功能全面但复杂;Sa-Token是"安全领域的美工刀",简单实用且灵活。

七、优缺点

优点

1. 极低的学习成本你几乎不需要理解任何底层原理,只需引入依赖、添加几行配置,就能让一个登录接口跑起来。开发者不需要先啃完一本安全理论书才能写出第一行代码。

2. 一行代码搞定认证 登录只需要StpUtil.login(id),校验登录只需要StpUtil.checkLogin()。大多数功能都可以一行代码解决。

3. 五大核心模块,功能全面目前已集成:登录认证、权限认证、分布式Session会话、微服务网关鉴权、单点登录、OAuth2.0、踢人下线、Redis集成、前后台分离、记住我模式、模拟他人账号、临时身份切换、账号封禁、多账号认证体系、注解式鉴权、路由拦截式鉴权、花式token生成、自动续签、同端互斥登录、会话治理、密码加密、jwt集成、Spring集成、WebFlux集成。

4. 开源免费,持续迭代2026年3月发布的v1.45.0已适配Spring Boot 4,新增了重复登录处理策略和Jackson3插件。

5. 与Spring生态完美集成支持Spring Boot 2/3/4、WebFlux、Solon、JFinal等常见框架。

缺点

1. 生态不如Spring Security成熟作为后起之秀,第三方集成和社区积累不如Spring Security。

2. 功能边界相对聚焦Sa-Token主要提供认证、授权和会话管理等功能。如果项目需要CSRF保护等更复杂的安全防护措施,Spring Security可能是更好的选择。

3. 部分高级功能需要额外配置虽然核心功能开箱即用,但JWT、SSO、OAuth2等高级功能需要引入独立插件。

八、适用场景

场景 推荐程度 理由
Spring Boot新项目 ✅✅✅ 强烈推荐 零配置启动,三天跑通权限系统
从Spring Security迁移 ✅✅✅ 强烈推荐 代码量直接砍一大截,学习成本极低
需要快速交付的项目 ✅✅✅ 强烈推荐 一行代码搞定登录认证
微服务架构 ✅✅✅ 强烈推荐 网关统一鉴权+Redis分布式会话
多端登录策略复杂 ✅✅✅ 强烈推荐 原生支持同端互斥登录、多端登录策略
团队对安全不熟悉 ✅✅✅ 强烈推荐 上手即用,不需要理解复杂的过滤器链
高安全/复杂合规需求 ⚠️ 需评估 Spring Security功能更全面

九、写在最后

回到最初的问题:为什么越来越多人用Sa-Token?

答案其实很简单------因为它解决了权限认证这个高频场景下的核心矛盾:既要功能强大,又要简单易用。

Spring Security虽然功能强大,但学习曲线陡峭,配置复杂。新手开发者常常陷入"我只是想加个登录,为什么需要理解整个过滤器链"的困惑中。

手写权限控制虽然灵活,但安全逻辑会像"幽灵代码"一样渗透到业务代码的每个角落。

Sa-Token走了一条"第三条路" ------基于核心-插件-适配器模型,既保持了核心的轻量和纯净,又通过插件机制提供了强大的扩展能力。

你只需要一行StpUtil.login(id),背后自动完成了Token生成、Session创建、Cookie注入等一系列工作。

路由拦截模式让你告别"每个接口都贴注解"的机械劳动。

分布式会话、踢人下线、多端登录策略------这些生产环境的刚需,全部原生支持。

从Spring Security到Sa-Token,不是"谁取代谁",而是在合适的场景选择更合适的工具

开源地址

相关推荐
众人皆醒我独醉1 小时前
Token:AI 世界的基本粒子——不是"字",是统计上最优的"字符组合"
后端·面试·llm
小当家.1052 小时前
深入理解 ReAct Agent:从原理到 Java 实战
java·react.js·agent·react·架构设计·agent设计
geminigoth2 小时前
Spring AI Alibaba 入门开发一(备份)
java·人工智能·spring
Hammer_Hans2 小时前
DFT笔记98
java·开发语言·数据库
古法安卓2 小时前
Android-DeviceStorageMonitorService 流程分析
java·面试·android studio
Java内核笔记2 小时前
Spring Boot 4 拥抱 Jackson 3:包名迁移、配置改名与自动配置源码剖析
java·后端
Hamm3 小时前
前端转Java+AI全栈?那我推荐几个实战开源项目给你
前端·后端·全栈
程序员黑豆3 小时前
什么是JDK以及JDK都由哪些部分组成呢
java·前端·ai编程
估值探索者3 小时前
【Python实时盯盘与预警 #08】成交额突然放大2倍?Python窗口比较抓异动
java·开发语言·python