Sa-Token 实战:如何解决 cn.dev33.satoken.exception.NotLoginException 异常

1次阅读
没有评论

共计 2984 个字符,预计需要花费 8 分钟才能阅读完成。

image.webp

异常解析与触发场景

NotLoginException是 Sa-Token 中最常见的异常之一,字面意思是 ” 未登录异常 ”。当框架在请求中未能读取到有效 token 时就会抛出这个异常。根据日常开发经验,主要会在以下场景触发:

Sa-Token 实战:如何解决 cn.dev33.satoken.exception.NotLoginException 异常

  1. 用户未登录直接访问需要认证的接口
  2. Token 已过期(默认有效期 30 分钟)
  3. Token 被手动删除或服务端主动注销
  4. 从不同设备登录导致前一个 token 失效
  5. Token 在传输过程中被篡改

Token 存储方案对比

Sa-Token 支持多种 token 存储方式,最常见的是通过 Cookie 和 Header 传递:

  • Cookie 方式
  • 优点:自动携带,无需前端处理
  • 缺点:受同源策略限制,跨域需要额外配置
  • 配置示例:

    @Bean
    public SaTokenConfig saTokenConfig() {SaTokenConfig config = new SaTokenConfig();
        config.setTokenStyle("simple");
        config.setTokenName("satoken"); // Cookie 名称
        config.setTimeout(30 * 60); // 30 分钟
        return config;
    }

  • Header 方式

  • 优点:适合前后端分离项目
  • 缺点:需要前端显式处理
  • 配置示例(在 application.yml 中):
    sa-token:
      token-name: Authorization
      is-read-header: true

完整异常处理方案

1. 全局异常拦截

Spring Boot 中统一处理异常:

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(NotLoginException.class)
    public Result handlerNotLoginException(NotLoginException e) {
        // 根据异常子类型细化提示
        String message = "";
        switch(e.getType()) {
            case NotLoginException.INVALID_TOKEN:
                message = "Token 无效"; break;
            case NotLoginException.TOKEN_TIMEOUT:
                message = "Token 已过期"; break;
            default:
                message = "请先登录";
        }
        return Result.error(401, message);
    }
}

2. Token 生成与刷新

登录接口示例:

@PostMapping("/login")
public Result login(@RequestBody LoginDTO dto) {
    // 1. 验证账号密码...

    // 2. 生成 token
    StpUtil.login(dto.getUserId());

    // 3. 返回 token 信息
    return Result.success("登录成功", StpUtil.getTokenInfo());
}

3. 自定义登录校验

可以继承 StpInterface 实现权限加载逻辑:

@Component
public class StpInterfaceImpl implements StpInterface {

    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {// 返回用户权限列表}

    @Override
    public List<String> getRoleList(Object loginId, String loginType) {// 返回用户角色列表}
}

性能优化建议

  1. 合理设置过期时间
  2. 短 token(如 30 分钟)配合长 token(7 天)实现自动续签
  3. 配置示例:

    // 在配置类中设置
    config.setTimeout(30 * 60); // 短 token
    config.setActivityTimeout(24 * 60 * 60); // 长 token

  4. 并发场景处理

  5. 启用 token 临时缓存(默认已开启)
  6. 对于高频接口,建议增加本地缓存:
    @SaCheckLogin
    @GetMapping("/userinfo")
    @Cacheable(value = "user", key = "#userId")
    public UserInfo getUserInfo(@RequestParam String userId) {// ...}

安全注意事项

  1. 防止 Token 泄露
  2. 务必使用 HTTPS 传输
  3. 不要在前端 JS 中存储 token
  4. 敏感操作需要二次验证

  5. CSRF 防护

  6. 启用 Sa-Token 的 CSRF 防护:
    @Bean
    public SaTokenConfig saTokenConfig() {SaTokenConfig config = new SaTokenConfig();
        config.setTokenName("satoken");
        config.setIsReadHeader(true);
        config.setIsV(true); // 开启 CSRF 防御
        return config;
    }

Spring Boot 集成示例

完整配置类示例:

@Configuration
public class SaTokenConfigure implements WebMvcConfigurer {

    // 注册 Sa-Token 配置
    @Bean
    public SaTokenConfig saTokenConfig() {SaTokenConfig config = new SaTokenConfig();
        config.setTokenName("Authorization");
        config.setTimeout(30 * 60);
        config.setActivityTimeout(-1); // - 1 表示不限制
        config.setIsConcurrent(true); // 允许并发登录
        config.setIsShare(true); // 共享 token
        return config;
    }

    // 注册拦截器
    @Override
    public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new SaAnnotationInterceptor())
            .addPathPatterns("/**")
            .excludePathPatterns("/login", "/error");
    }
}

扩展思考

在实际项目中,我们还需要考虑:

  1. 分布式环境下的 Token 同步
  2. 可以结合 Redis 实现 token 集中存储
  3. 使用 Sa-Token 的分布式模块:

    <dependency>
        <groupId>cn.dev33</groupId>
        <artifactId>sa-token-redis</artifactId>
        <version> 最新版本 </version>
    </dependency>

  4. 多端登录管理

  5. 通过不同 loginType 区分设备类型
  6. 示例代码:
    // PC 端登录
    StpUtil.login(10001, "PC");
    // 移动端登录 
    StpUtil.login(10001, "APP");

通过本文的介绍,相信你已经掌握了 Sa-Token 中 NotLoginException 异常的处理方法。建议在实际项目中根据业务需求灵活调整 token 策略,并在开发过程中做好异常监控和日志记录。

正文完
 0
评论(没有评论)