Skip to content

sa-token 与 Spring Security

概述

在 Java Web 开发中,权限认证是不可或缺的一环。sa-token 和 Spring Security 是目前最流行的两个权限认证框架。本文将从多个维度对比这两个框架,帮助开发者根据项目需求选择合适的解决方案。

框架简介

sa-token

sa-token 是一个轻量级 Java 权限认证框架,专注于解决系统的认证授权、单点登录、OAuth2.0、微服务网关鉴权等一系列权限相关问题。

核心特点:

  • 轻量级,代码简洁易懂
  • 功能全面,开箱即用
  • 学习曲线平缓
  • 支持多种集成方式

Spring Security

Spring Security 是 Spring 生态中的安全框架,提供了全面的安全解决方案,包括认证、授权、防护等功能。

核心特点:

  • 功能强大,生态完善
  • 深度集成 Spring 框架
  • 企业级安全标准
  • 高度可定制化

详细对比

1. 学习曲线

对比项sa-tokenSpring Security
入门难度⭐⭐ 简单⭐⭐⭐⭐ 较难
概念理解直观易懂需要理解多个抽象概念
文档友好度中文文档详细,示例丰富英文文档为主,较为复杂
上手时间1-2 天1-2 周

sa-token 示例:

java
// 登录
StpUtil.login(10001);

// 获取当前用户ID
long userId = StpUtil.getLoginIdAsLong();

// 校验权限
StpUtil.checkPermission("user:delete");

// 登出
StpUtil.logout();

Spring Security 示例:

java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .logout();
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("admin")
            .password(passwordEncoder().encode("123456"))
            .roles("ADMIN");
    }
}

2. 功能对比

功能特性sa-tokenSpring Security
登录认证
权限认证
踢人下线⚠️ 需额外实现
账号封禁⚠️ 需额外实现
同端互斥登录⚠️ 需额外实现
多账号体系⚠️ 复杂配置
Session 会话
Token 认证
SSO 单点登录✅ 内置支持⚠️ 需集成其他方案
OAuth2.0
二级认证⚠️ 需自定义
独立 Redis⚠️ 需额外配置
前后端分离✅ 天然支持
分布式 Session⚠️ 需 Spring Session
微服务鉴权

3. 性能对比

sa-token:

  • 轻量级设计,内存占用小
  • 响应速度快,单次验证耗时约 0.01-0.1ms
  • 支持高并发场景
  • 可选的 Redis 缓存优化

Spring Security:

  • 功能全面但相对较重
  • 默认配置下性能良好
  • 企业级场景下经过充分验证
  • 可通过优化配置提升性能

4. 使用场景

sa-token 适用场景

  • 中小型项目快速开发
  • 需要快速实现权限功能
  • 团队技术栈偏向轻量化
  • 需要灵活的会话管理
  • 移动端 App 开发
  • 微服务架构下的轻量化鉴权

Spring Security 适用场景

  • 大型企业级应用
  • 对安全性要求极高的系统
  • 深度使用 Spring 生态
  • 需要复杂的安全策略
  • 金融、医疗等行业应用
  • 需要符合特定安全标准(如 OAuth2、SAML)

5. 集成便捷性

sa-token 集成步骤:

  1. 添加依赖
xml
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.37.0</version>
</dependency>
  1. 配置文件
yaml
sa-token:
  token-name: satoken
  timeout: 2592000
  active-timeout: -1
  is-concurrent: true
  is-share: true
  token-style: uuid
  1. 直接使用
java
@RestController
public class UserController {
    @PostMapping("/login")
    public String login(String username, String password) {
        // 验证账号密码(此处仅做示例)
        if ("admin".equals(username) && "123456".equals(password)) {
            StpUtil.login(10001);
            return "登录成功";
        }
        return "登录失败";
    }
}

Spring Security 集成步骤:

  1. 添加依赖
xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. 配置安全策略(需要编写较多配置类)
  2. 实现 UserDetailsService
  3. 配置密码加密器
  4. 自定义认证成功/失败处理器

6. 社区与生态

对比项sa-tokenSpring Security
社区活跃度活跃(国内)非常活跃(全球)
文档质量优秀(中文)优秀(英文为主)
更新频率频繁稳定
插件生态逐步完善非常丰富
企业采用中小企业为主各规模企业

代码示例对比

权限验证

sa-token:

java
// 注解方式
@SaCheckPermission("user:delete")
@DeleteMapping("/user/{id}")
public String deleteUser(@PathVariable Long id) {
    return "删除成功";
}

// 代码方式
if (StpUtil.hasPermission("user:delete")) {
    // 有权限,执行删除
}

Spring Security:

java
// 注解方式
@PreAuthorize("hasAuthority('user:delete')")
@DeleteMapping("/user/{id}")
public String deleteUser(@PathVariable Long id) {
    return "删除成功";
}

// 代码方式
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth.getAuthorities().stream()
    .anyMatch(a -> a.getAuthority().equals("user:delete"))) {
    // 有权限,执行删除
}

踢人下线

sa-token:

java
// 踢掉指定账号
StpUtil.kickout(10001);

// 踢掉指定客户端
StpUtil.kickoutByTokenValue("token-value");

Spring Security:

java
// 需要自己实现 SessionRegistry 和相关逻辑
@Autowired
private SessionRegistry sessionRegistry;

public void kickout(String username) {
    List<SessionInformation> sessions = sessionRegistry
        .getAllSessions(username, false);
    for (SessionInformation session : sessions) {
        session.expireNow();
    }
}

分布式会话

sa-token:

xml
<!-- 添加 Redis 依赖 -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-dao-redis-jackson</artifactId>
    <version>1.37.0</version>
</dependency>

配置即可自动使用 Redis 存储会话。

Spring Security: 需要集成 Spring Session:

xml
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session-data-redis</artifactId>
</dependency>

并进行额外配置。

选型建议

选择 sa-token 的理由

  1. 项目周期紧:需要快速实现权限功能
  2. 团队经验有限:团队成员对安全框架不够熟悉
  3. 功能需求明确:需要踢人下线、账号封禁等开箱即用的功能
  4. 轻量化优先:追求简洁的代码和快速的响应
  5. 中文文档优势:团队更适应中文文档

选择 Spring Security 的理由

  1. 企业级应用:大型、复杂的企业级系统
  2. 深度集成 Spring:项目深度使用 Spring 全家桶
  3. 安全标准要求:需要符合特定的行业安全标准
  4. 长期维护:Spring 官方长期支持,稳定性有保障
  5. 复杂安全策略:需要实现复杂的安全规则和策略

混合使用

在某些场景下,也可以考虑混合使用:

  • 使用 Spring Security 处理核心认证授权
  • 使用 sa-token 的特定功能(如踢人下线、SSO 等)

迁移建议

从 Spring Security 迁移到 sa-token

优势:

  • 代码量大幅减少
  • 维护成本降低
  • 新功能实现更快

注意事项:

  • 需要重构现有的认证授权代码
  • 测试工作量较大
  • 需要评估现有安全策略的实现

从 sa-token 迁移到 Spring Security

优势:

  • 更强的企业级能力
  • 更好的 Spring 生态集成
  • 符合更多安全标准

注意事项:

  • 学习成本较高
  • 开发周期会延长
  • 需要重新设计安全架构

总结

sa-token 和 Spring Security 各有优势,没有绝对的好坏之分:

  • sa-token 适合追求快速开发、代码简洁的项目,特别是中小型应用和微服务场景
  • Spring Security 适合对安全性要求高、需要深度定制的大型企业级应用

选择框架时,应该综合考虑:

  • 项目规模和复杂度
  • 团队技术能力
  • 开发时间要求
  • 长期维护成本
  • 安全性要求

无论选择哪个框架,都应该遵循安全最佳实践,定期更新依赖版本,及时修复安全漏洞。

参考资源

Released under the MIT License.