首页
/ Sa-Token中NotLoginException异常处理的最佳实践

Sa-Token中NotLoginException异常处理的最佳实践

2025-05-12 07:50:05作者:魏侃纯Zoe

问题背景

在使用Sa-Token框架进行权限控制时,开发者经常会遇到一个典型场景:当用户访问一个不存在的接口时,系统会抛出NotLoginException异常,但这个异常无法被RestControllerAdvice捕获,导致无法统一处理异常响应。

问题分析

在Sa-Token的拦截器配置中,通常会使用SaInterceptor对所有API路径进行登录校验。当用户访问一个不存在的接口时,Spring框架会先经过SaInterceptor进行鉴权,此时如果用户未登录,Sa-Token会抛出NotLoginException。然而由于接口本身不存在,Spring框架会将其视为404错误,导致RestControllerAdvice无法捕获这个异常。

解决方案

方案一:自定义ErrorController

通过实现Spring Boot的ErrorController接口,可以统一处理所有错误请求:

@RestController
@RequestMapping("/error")
public class ErrorController {
    
    @RequestMapping("/404")
    public ResponseResult<Void> handle404() {
        return ResponseResult.fail(ResponseCodeEnum.NOT_FOUND);
    }
    
    @RequestMapping("/500")
    public ResponseResult<Void> handle500() {
        return ResponseResult.exception();
    }
}

这种方式的优点是实现简单,可以统一处理所有错误状态码。缺点是会丢失原始异常信息,无法针对NotLoginException做特殊处理。

方案二:预检查URI有效性

在SaInterceptor之前添加一个自定义拦截器,预先检查请求URI是否存在:

@Component
public class NoApiInterceptor implements HandlerInterceptor {
    
    private final Set<String> allUriSet = new HashSet<>();
    private final WebApplicationContext applicationContext;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if (allUriSet.isEmpty()) {
            allUriSet.addAll(getAllUri());
        }
        
        String path = request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE).toString();
        if (!allUriSet.contains(path)) {
            // 返回404响应
            return false;
        }
        return true;
    }
    
    private List<String> getAllUri() {
        RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
        return mapping.getHandlerMethods().keySet().stream()
                .flatMap(info -> info.getPathPatternsCondition().getPatterns().stream())
                .map(PathPattern::toString)
                .collect(Collectors.toList());
    }
}

然后在配置类中确保这个拦截器优先执行:

@Configuration
public class InterceptorConfigure implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new NoApiInterceptor()).addPathPatterns("/api/**");
        registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
                .addPathPatterns("/api/**")
                .excludePathPatterns("/api/v1/account/login");
    }
}

这种方案的优点是可以精确控制流程,避免不必要的异常抛出。缺点是需要维护URI缓存,且在应用启动时需要扫描所有Controller。

方案三:使用SaServletFilter全局处理

Sa-Token提供了SaServletFilter,可以更优雅地处理这类问题:

@Bean
public SaServletFilter saServletFilter() {
    return new SaServletFilter()
            .addInclude("/**")
            .addExclude("/error")
            .setAuth(obj -> {
                SaRouter.match("/**", () -> StpUtil.checkLogin());
            })
            .setError(e -> {
                // 统一异常处理
                return handleException(e);
            });
}

这种方式的优势在于:

  1. 可以统一处理所有异常
  2. 避免异常被Spring框架拦截
  3. 配置更加灵活

最佳实践建议

  1. 生产环境推荐:使用方案三(SaServletFilter)结合方案一(ErrorController),既能统一处理异常,又能保证404等错误的友好响应。

  2. 性能考虑:如果系统接口数量庞大,方案二中的URI缓存可能会占用较多内存,此时方案三更为合适。

  3. 异常监控:如果系统有异常监控需求,可以在SaServletFilter的setError方法中添加日志记录逻辑。

  4. 前后端分离:确保所有错误响应都采用统一的JSON格式,便于前端处理。

通过以上方案,开发者可以优雅地解决Sa-Token中NotLoginException异常处理的问题,同时保持系统的统一错误处理机制。

登录后查看全文
热门项目推荐

项目优选

收起
RuoYi-Vue3RuoYi-Vue3
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
852
505
kernelkernel
deepin linux kernel
C
21
5
openHiTLSopenHiTLS
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
240
283
ShopXO开源商城ShopXO开源商城
🔥🔥🔥ShopXO企业级免费开源商城系统,可视化DIY拖拽装修、包含PC、H5、多端小程序(微信+支付宝+百度+头条&抖音+QQ+快手)、APP、多仓库、多商户、多门店、IM客服、进销存,遵循MIT开源协议发布、基于ThinkPHP8框架研发
JavaScript
93
15
UAVSUAVS
智能无人机路径规划仿真系统是一个具有操作控制精细、平台整合性强、全方向模型建立与应用自动化特点的软件。它以A、B两国在C区开展无人机战争为背景,该系统的核心功能是通过仿真平台规划无人机航线,并进行验证输出,数据可导入真实无人机,使其按照规定路线精准抵达战场任一位置,支持多人多设备编队联合行动。
JavaScript
78
55
nop-entropynop-entropy
Nop Platform 2.0是基于可逆计算理论实现的采用面向语言编程范式的新一代低代码开发平台,包含基于全新原理从零开始研发的GraphQL引擎、ORM引擎、工作流引擎、报表引擎、规则引擎、批处理引引擎等完整设计。nop-entropy是它的后端部分,采用java语言实现,可选择集成Spring框架或者Quarkus框架。中小企业可以免费商用
Java
7
0
vue-devuivue-devui
基于全新 DevUI Design 设计体系的 Vue3 组件库,面向研发工具的开源前端解决方案。
TypeScript
614
74
ohos_react_nativeohos_react_native
React Native鸿蒙化仓库
C++
175
260
CangjieCommunityCangjieCommunity
为仓颉编程语言开发者打造活跃、开放、高质量的社区环境
Markdown
1.07 K
0
Cangjie-ExamplesCangjie-Examples
本仓将收集和展示高质量的仓颉示例代码,欢迎大家投稿,让全世界看到您的妙趣设计,也让更多人通过您的编码理解和喜爱仓颉语言。
Cangjie
331
1.07 K