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-token | Spring 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-token | Spring 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 集成步骤:
- 添加依赖
xml
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.37.0</version>
</dependency>- 配置文件
yaml
sa-token:
token-name: satoken
timeout: 2592000
active-timeout: -1
is-concurrent: true
is-share: true
token-style: uuid- 直接使用
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 集成步骤:
- 添加依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>- 配置安全策略(需要编写较多配置类)
- 实现 UserDetailsService
- 配置密码加密器
- 自定义认证成功/失败处理器
6. 社区与生态
| 对比项 | sa-token | Spring 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 的理由
- 项目周期紧:需要快速实现权限功能
- 团队经验有限:团队成员对安全框架不够熟悉
- 功能需求明确:需要踢人下线、账号封禁等开箱即用的功能
- 轻量化优先:追求简洁的代码和快速的响应
- 中文文档优势:团队更适应中文文档
选择 Spring Security 的理由
- 企业级应用:大型、复杂的企业级系统
- 深度集成 Spring:项目深度使用 Spring 全家桶
- 安全标准要求:需要符合特定的行业安全标准
- 长期维护:Spring 官方长期支持,稳定性有保障
- 复杂安全策略:需要实现复杂的安全规则和策略
混合使用
在某些场景下,也可以考虑混合使用:
- 使用 Spring Security 处理核心认证授权
- 使用 sa-token 的特定功能(如踢人下线、SSO 等)
迁移建议
从 Spring Security 迁移到 sa-token
优势:
- 代码量大幅减少
- 维护成本降低
- 新功能实现更快
注意事项:
- 需要重构现有的认证授权代码
- 测试工作量较大
- 需要评估现有安全策略的实现
从 sa-token 迁移到 Spring Security
优势:
- 更强的企业级能力
- 更好的 Spring 生态集成
- 符合更多安全标准
注意事项:
- 学习成本较高
- 开发周期会延长
- 需要重新设计安全架构
总结
sa-token 和 Spring Security 各有优势,没有绝对的好坏之分:
- sa-token 适合追求快速开发、代码简洁的项目,特别是中小型应用和微服务场景
- Spring Security 适合对安全性要求高、需要深度定制的大型企业级应用
选择框架时,应该综合考虑:
- 项目规模和复杂度
- 团队技术能力
- 开发时间要求
- 长期维护成本
- 安全性要求
无论选择哪个框架,都应该遵循安全最佳实践,定期更新依赖版本,及时修复安全漏洞。
参考资源
- sa-token 官方文档: https://sa-token.cc
- Spring Security 官方文档: https://docs.spring.io/spring-security
- sa-token GitHub: https://github.com/dromara/sa-token
- Spring Security GitHub: https://github.com/spring-projects/spring-security
