news 2026/7/18 6:43:09

Sa-Token解决跨域问题的三种实践方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Sa-Token解决跨域问题的三种实践方案

1. 为什么需要处理跨域问题?

跨域问题源于浏览器的同源策略(Same-Origin Policy),这是现代浏览器最基本的安全机制之一。简单来说,当你的前端页面(比如运行在http://localhost:8080)尝试通过AJAX请求后端API(比如http://api.example.com)时,浏览器会阻止这种请求,除非后端明确允许。

在实际开发中,前后端分离架构已经成为主流,前端可能部署在CDN或独立域名下,后端API则有专门的域名。这种情况下,跨域问题几乎不可避免。我曾接手过一个电商项目,前端使用Vue.js部署在static.shop.com,而后端API在api.shop.com,就因为没处理好CORS导致支付功能完全无法使用。

提示:即使前端和后端在同一台服务器,如果端口不同(如前端3000端口,后端8080端口)也会触发跨域限制。

2. Sa-Token全局过滤器基础配置

2.1 添加Sa-Token依赖

首先需要在项目中引入Sa-Token核心库。以Maven项目为例:

<dependency> <groupId>cn.dev33</groupId> <artifactId>sa-token-spring-boot-starter</artifactId> <version>1.45.0</version> </dependency>

我建议始终使用最新稳定版,因为Sa-Token团队会持续修复CORS相关的边界问题。曾经有个项目使用了较旧的1.38.0版本,在处理OPTIONS预检请求时会出现奇怪的拦截行为。

2.2 创建基础过滤器类

创建一个继承自SaServletFilter的全局过滤器:

@Configuration public class SaTokenFilter implements SaServletFilter { @Override public void addExcludes(String... paths) { // 不需要过滤的路径 } @Override public void setAuth(Object handler) { // 认证逻辑 } @Override public void setBeforeAuth(Object handler) { // 前置处理 } }

这个基础结构是三种解决方案的共同起点。注意setBeforeAuth方法,这是我们后续处理CORS的关键切入点。

3. 方案一:纯Sa-Token过滤器实现

3.1 核心代码实现

在setBeforeAuth方法中添加CORS处理逻辑:

@Override public void setBeforeAuth(Object handler) { HttpServletRequest request = (HttpServletRequest) handler; HttpServletResponse response = (HttpServletResponse) handler; // 设置允许的源 response.setHeader("Access-Control-Allow-Origin", "*"); // 允许的请求方法 response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); // 预检请求缓存时间 response.setHeader("Access-Control-Max-Age", "3600"); // 允许的请求头 response.setHeader("Access-Control-Allow-Headers", "x-requested-with, sa-token, Content-Type"); }

3.2 实际项目中的坑点

  1. 星号(*)限制:虽然设置为*很方便,但在需要传递cookie时(比如单点登录场景)必须指定具体域名,且要设置Access-Control-Allow-Credentials: true。我曾在SSO集成时花了半天排查为什么cookie不生效。

  2. OPTIONS请求处理:浏览器会先发送OPTIONS预检请求。很多开发者只处理了GET/POST却漏了OPTIONS,导致PUT/DELETE等方法失败。务必确保所有方法都被列出。

  3. Header大小写敏感:有些前端框架会自动转换header名称大小写,而后端可能区分大小写。建议统一使用小写,比如sa-token而非Sa-Token

4. 方案二:结合Spring的CorsRegistry

4.1 混合配置方式

如果你同时使用Spring MVC,可以结合两种方案:

@Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("*") .allowedHeaders("*") .exposedHeaders("sa-token"); } } // 同时在SaTokenFilter中保留基础CORS设置

这种组合方式特别适合大型项目,可以利用Spring更细粒度的路径控制,同时保持Sa-Token的认证逻辑。

4.2 优先级问题

Spring的CORS配置和Sa-Token过滤器的执行顺序很重要。实测发现:

  1. 简单请求(GET/POST):先经过Spring CORS,再到Sa-Token
  2. 复杂请求(PUT/DELETE等):OPTIONS请求会被Spring优先处理

这意味着如果你的Sa-Token过滤器对OPTIONS请求有特殊逻辑,可能需要调整。一个保险的做法是在SaTokenFilter中增加判断:

if ("OPTIONS".equals(request.getMethod())) { return; }

5. 方案三:基于注解的精细控制

5.1 @SaCheckCors注解实现

对于需要特殊CORS规则的接口,可以创建自定义注解:

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface SaCheckCors { String[] origins() default "*"; String[] methods() default {"GET", "POST"}; String[] headers() default {}; }

然后在过滤器中解析注解:

HandlerMethod handlerMethod = (HandlerMethod)handler; SaCheckCors corsConfig = handlerMethod.getMethodAnnotation(SaCheckCors.class); if (corsConfig != null) { response.setHeader("Access-Control-Allow-Origin", String.join(",", corsConfig.origins())); // 其他header设置... }

5.2 实际应用场景

这种方案特别适合:

  • 某些接口需要开放给特定合作伙伴域名
  • 不同接口支持不同的HTTP方法
  • 需要动态调整CORS策略的灰度发布场景

比如支付回调接口可能只允许来自支付平台的POST请求:

@PostMapping("/pay/callback") @SaCheckCors(origins = "https://payment-platform.com", methods = "POST") public Result payCallback() { // ... }

6. 生产环境最佳实践

6.1 安全加固建议

  1. 不要无脑使用*:根据项目实际需要设置允许的源,可以配置在application.yml中:
sa-token: cors: allowed-origins: - https://www.yourdomain.com - https://admin.yourdomain.com
  1. 限制暴露的Header:只暴露必要的Header,避免泄露敏感信息:
response.setHeader("Access-Control-Expose-Headers", "sa-token, content-length");
  1. 结合HTTPS:CORS+HTTP是不安全的组合,生产环境必须启用HTTPS。

6.2 性能优化

  1. 合理设置Max-Age:对于稳定的API,可以设置较长的缓存时间减少OPTIONS请求:
response.setHeader("Access-Control-Max-Age", "86400"); // 24小时
  1. 避免重复处理:在过滤器中添加判断,已经处理过的请求不再重复设置Header:
if (response.getHeader("Access-Control-Allow-Origin") != null) { return; }
  1. 网关层统一处理:如果项目使用微服务架构,可以考虑在API网关统一处理CORS,避免每个服务重复配置。

7. 疑难问题排查指南

7.1 常见错误现象

  1. 控制台报错但服务端日志无记录:通常是浏览器拦截了请求,根本未到达服务端。检查网络面板确认请求是否真的发出。

  2. POST变成OPTIONS:这是正常预检机制,检查你的服务是否正确响应了OPTIONS方法。

  3. 明明配置了CORS还是报错

    • 检查是否有多个过滤器/拦截器覆盖了CORS头
    • 使用curl测试确认响应头是否正确:
      curl -I -X OPTIONS http://your-api.com/endpoint

7.2 调试技巧

  1. 浏览器无痕模式测试:避免缓存干扰,Chrome的隐身窗口是最干净的测试环境。

  2. 简化复现:创建一个最小化的测试接口,排除业务逻辑干扰:

@GetMapping("/test-cors") public String testCors() { return "CORS test"; }
  1. 查看完整请求链路:使用Charles或Fiddler抓包,对比请求和响应的完整Header信息。

8. 三种方案对比与选型建议

8.1 方案对比表

特性纯Sa-Token方案Spring混合方案注解方案
实现复杂度
灵活性一般较好最好
性能影响较小中等
适合场景简单项目Spring项目需要精细控制
维护成本较高

8.2 个人经验建议

根据我参与过的十几个项目经验:

  1. 初创项目/快速原型:选择方案一,简单直接,10分钟搞定。

  2. 标准Spring Boot应用:方案二最平衡,既利用Spring生态,又保持Sa-Token特性。

  3. 企业级复杂系统:特别是需要对接多第三方系统时,方案三的精细控制必不可少。

一个实际案例:我们有个金融项目需要对接5个外部支付渠道,每个渠道的CORS要求都不同,最终采用方案三为每个渠道接口单独配置,大大降低了维护难度。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/18 6:41:24

STM32定时器中断原理与实现教程

1. STM32定时器中断基础概念在嵌入式系统开发中&#xff0c;定时器中断是最基础也最重要的功能之一。STM32系列单片机提供了丰富的定时器资源&#xff0c;其中TIM2作为通用定时器&#xff0c;非常适合初学者入门学习。定时器中断的核心原理是通过硬件计数器实现精准的时间控制。…

作者头像 李华
网站建设 2026/7/18 6:41:09

GPIO接口详解:从基础概念到高级应用

1. GPIO基础概念与核心特性解析GPIO&#xff08;General Purpose Input/Output&#xff09;作为现代嵌入式系统的"万能接口"&#xff0c;其重要性不亚于人类神经末梢对于感知外界的作用。这种可编程数字接口允许开发者通过软件配置实现输入检测或输出控制&#xff0c…

作者头像 李华
网站建设 2026/7/18 6:40:52

UE5 MetaHuman实时口型同步:NVIDIA Audio2Face与Omniverse流送实战

1. 项目概述&#xff1a;当UE5的MetaHuman遇见NVIDIA Audio2Face如果你正在用UE5开发需要角色对话的游戏或数字人应用&#xff0c;肯定遇到过这个头疼的问题&#xff1a;如何让MetaHuman角色的口型与语音完美同步&#xff1f;手动逐帧调整动画&#xff1f;那简直是噩梦。用传统…

作者头像 李华
网站建设 2026/7/18 6:40:02

ExpressJS与现代Node.js框架的对比与迁移策略

1. 为什么开发者开始质疑ExpressJS的适用性2021年对于Node.js生态来说是个关键转折点。那一年Node.js 16发布&#xff0c;带来了稳定的ES模块支持和改进的Worker Threads实现&#xff0c;而社区对现代异步编程模式的需求也达到了新高度。ExpressJS作为一个诞生于2010年的"…

作者头像 李华
网站建设 2026/7/18 6:39:52

CyberChef完整指南:快速掌握网络数据操作的瑞士军刀

CyberChef完整指南&#xff1a;快速掌握网络数据操作的瑞士军刀 【免费下载链接】CyberChef The Cyber Swiss Army Knife - a web app for encryption, encoding, compression and data analysis 项目地址: https://gitcode.com/GitHub_Trending/cy/CyberChef CyberChef…

作者头像 李华
网站建设 2026/7/18 6:39:25

文档太多理不清?Qwen-Agent智能文档处理让AI帮你搞定一切

文档太多理不清&#xff1f;Qwen-Agent智能文档处理让AI帮你搞定一切 【免费下载链接】Qwen-Agent Agent framework and applications built upon Qwen>3.0, featuring Function Calling, MCP, Code Interpreter, RAG, Chrome extension, etc. 项目地址: https://gitcode.…

作者头像 李华