Sa-Token 跨域配置导致 Token 失效问题分析与解决方案
问题背景
在使用 Sa-Token 1.43.0 版本时,开发者遇到了一个典型的跨域问题:在配置了跨域支持后,系统无法正确识别和验证 Token,导致出现"未能读取到有效 token"和"SaTokenContext 上下文尚未初始化"的错误。
错误现象分析
从错误日志中可以观察到两个关键问题:
- Token 读取失败:系统抛出 NotLoginException,表明未能从请求中获取到有效的 Token
- 上下文初始化问题:SaTokenContext 上下文未正确初始化,导致后续操作无法进行
问题根源
通过分析配置代码,发现问题的核心在于跨域配置的冲突和不完整:
- 双重跨域配置:同时使用了 Spring 的 addCorsMappings 和 Sa-Token 的 corsHandle,导致处理流程混乱
- 预检请求处理不当:OPTIONS 请求未正确放行,影响了正常请求的 Token 传递
- 上下文丢失:跨域过滤器执行顺序不当,导致 Sa-Token 上下文未能正确建立
解决方案
1. 统一跨域配置方式
建议只使用 Sa-Token 提供的跨域处理方式,移除 Spring 的 addCorsMappings 配置:
@Bean
fun corsHandle(): SaCorsHandleFunction {
return SaCorsHandleFunction { req, res, _ ->
// 获取请求来源
var origin = req.getHeader("Origin") ?: req.getHeader("Referer")
// 设置跨域响应头
res.apply {
setHeader("Access-Control-Allow-Credentials", "true")
setHeader("Access-Control-Allow-Origin", origin)
setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
setHeader("Access-Control-Allow-Headers", "*")
setHeader("Access-Control-Max-Age", "3600")
}
// 放行OPTIONS预检请求
if (SaHttpMethod.OPTIONS == req.method) {
SaRouter.back()
}
}
}
2. 确保 Token 名称一致性
检查并确保以下两处的 Token 名称一致:
- 应用配置中的 sa-token.token-name
- 前端请求头中的 Authorization 字段名
3. 拦截器配置优化
调整拦截器配置,确保在正确的位置获取和验证 Token:
override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(SaInterceptor {
// 实际业务中可能需要更详细的日志记录
StpUtil.checkLogin()
}).addPathPatterns("/**")
.excludePathPatterns("/auth/login", "/openapi.html", "/openapi.yml", "/ts.zip")
}
最佳实践建议
- 单一跨域配置:选择一种跨域解决方案(推荐使用 Sa-Token 内置方案),避免多重配置
- 预检请求处理:确保 OPTIONS 请求被正确识别和放行
- 上下文验证:在关键位置添加上下文验证逻辑,确保 SaTokenContext 已初始化
- 日志记录:在关键流程中添加详细的日志记录,便于问题排查
- 移动端适配:特别注意移动端与Web端的差异,确保Token传递方式一致
总结
Sa-Token 的跨域问题通常源于配置冲突和流程顺序不当。通过统一跨域处理方式、确保Token传递一致性以及优化拦截器配置,可以有效解决这类问题。在实际开发中,建议遵循"配置单一化、流程清晰化"的原则,避免复杂的交叉配置带来的不可预期行为。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



