从Spring Security到Sa-Token:RuoYi-Vue-Plus 3.5.0权限系统改造实战

在Java企业级开发领域,权限管理始终是绕不开的核心模块。最近半年,技术社区关于Sa-Token的讨论热度持续攀升——这个由国内开发者开源的轻量级权限认证框架,正在以惊人的速度改变着传统Spring Security一家独大的格局。作为RuoYi-Vue-Plus框架的深度使用者,我在三个实际项目中完成了从Spring Security到Sa-Token的迁移,最直观的感受是:原来权限管理可以如此简单高效。

1. 为什么选择Sa-Token?

Spring Security的强大与痛点 就像一把双刃剑。我们团队曾花费两周时间才让OAuth2集成正常运作,复杂的过滤器链和晦涩的配置方式让新成员望而生畏。直到发现Sa-Token的这几个特性,才意识到权限框架还可以这样设计:

  • 会话管理 :内置的会话中心支持分布式环境下的会话管理,无需额外集成Spring Session
  • 注解式权限控制 :相比Security的复杂表达式, @SaCheckPermission("user:add") 的直观程度令人惊艳
  • 踢人下线 :一行代码实现 StpUtil.kickout(10001) ,这在Security中需要自定义实现
  • 无状态登录 :JWT集成开箱即用,配置项比Security减少70%
// Sa-Token的典型权限检查写法
@SaCheckLogin
@SaCheckPermission("system:user:list")
@GetMapping("/list")
public R list(SysUser user) {
    // 业务逻辑
}

2. 迁移前的准备工作

2.1 环境梳理

在RuoYi-Vue-Plus 3.5.0主分支中,Spring Security的配置主要分布在三个关键位置:

文件路径 核心功能 替代方案
SecurityConfig.java 安全配置入口 SaTokenConfig
JwtAuthenticationTokenFilter JWT校验过滤器 SaToken的StpUtil
SecurityUtils 权限工具类 直接使用StpUtil

重要提醒 :迁移前务必做好版本控制。建议新建git分支:

git checkout -b feature/sa-token-migration

2.2 依赖调整

修改pom.xml时需要注意版本兼容性。以下是经过验证的稳定组合:

<!-- 移除Spring Security相关依赖 -->
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-spring-boot-starter</artifactId>
    <version>1.34.0</version>
</dependency>
<dependency>
    <groupId>cn.dev33</groupId>
    <artifactId>sa-token-jwt</artifactId>
    <version>1.34.0</version>
</dependency>

3. 核心改造步骤

3.1 配置类重写

新建 SaTokenConfig.java 替代原来的Security配置:

@Configuration
public class SaTokenConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SaInterceptor())
            .addPathPatterns("/**")
            .excludePathPatterns("/login", "/captchaImage");
    }
    
    @Bean
    public StpLogic getStpLogicJwt() {
        return new StpLogicJwtForSimple();
    }
}

3.2 登录流程改造

原Spring Security的登录流程通常涉及多个过滤器,而Sa-Token将其简化为:

  1. 验证用户名密码
  2. 调用 StpUtil.login(userId)
  3. 返回token给前端

具体实现示例:

public String login(String username, String password) {
    // 验证账号密码
    Authentication authentication = authenticationManager
        .authenticate(new UsernamePasswordAuthenticationToken(username, password));
    
    // Sa-Token登录
    LoginUser loginUser = (LoginUser) authentication.getPrincipal();
    StpUtil.login(loginUser.getUserId());
    
    // 生成并返回Token
    return StpUtil.getTokenValue();
}

3.3 权限校验迁移

Spring Security的权限校验通常通过 @PreAuthorize 实现,Sa-Token提供了更简洁的注解:

Spring Security Sa-Token 功能说明
@PreAuthorize("hasRole('admin')") @SaCheckRole("admin") 角色校验
@PreAuthorize("hasAuthority('user:add')") @SaCheckPermission("user:add") 权限校验
@PreAuthorize("isAuthenticated()") @SaCheckLogin 登录校验

4. 深度集成技巧

4.1 会话持久化优化

RuoYi默认使用Redis作为缓存,我们可以利用这点优化Sa-Token的持久化:

@Component
public class PlusSaTokenDao implements SaTokenDao {
    @Override
    public String get(String key) {
        return RedisUtils.getCacheObject(key);
    }
    
    @Override
    public void set(String key, String value, long timeout) {
        if(timeout == NEVER_EXPIRE) {
            RedisUtils.setCacheObject(key, value);
        } else {
            RedisUtils.setCacheObject(key, value, timeout, TimeUnit.SECONDS);
        }
    }
}

4.2 自定义Token风格

Sa-Token支持多种Token生成策略,以下是JWT风格的配置示例:

sa-token: 
    token-name: satoken
    timeout: 86400
    token-style: uuid
    jwt-secret-key: ruoyi-plus-3.5.0-secret

5. 常见问题解决方案

在实际迁移过程中,我们遇到了几个典型问题:

  1. 会话冲突问题 :当同一个账号在不同设备登录时,Sa-Token默认配置会踢掉前一个登录。解决方案:

    // 在配置类中设置允许并发登录
    @PostConstruct
    public void setSaTokenConfig() {
        SaManager.getConfig().setIsConcurrent(true);
    }
    
  2. 权限缓存更新延迟 :修改用户权限后需要手动清除缓存:

    public void updateRolePermissions(Long roleId) {
        // 更新数据库逻辑...
        StpUtil.logoutByLoginId(roleId); // 强制该角色所有用户重新登录
    }
    
  3. 前后端Token传递 :前端需要在请求头中携带Token:

    axios.interceptors.request.use(config => {
        config.headers['satoken'] = localStorage.getItem('satoken')
        return config
    })
    

迁移完成后,我们项目的权限相关代码量减少了约40%,新成员上手时间从原来的3天缩短到3小时。特别是在微服务环境下,Sa-Token的分布式会话方案比Spring Security+OAuth2的组合轻量得多。当然,如果你的项目需要复杂的OAuth2流程,Spring Security可能仍是更好的选择。

更多推荐