1. 跨域问题的本质与Sa-Token的特殊性跨域问题CORS是前端开发中最常见的拦路虎之一。当你的前端应用尝试从不同域名、端口或协议的后端获取资源时浏览器会强制实施同源策略Same-Origin Policy这就是我们常遇到的has been blocked by CORS policy错误的根源。Sa-Token作为一个轻量级Java权限认证框架在跨域场景下会带来一些特殊问题。根据我的实战经验当项目同时存在以下特征时跨域问题会尤为突出使用Sa-Token的header头提交token如Authorization: Bearer xxxx前端与后端分离部署不同域名/端口涉及非简单请求如PUT/DELETE方法或自定义header关键误区很多开发者认为只要在SpringBoot中配置CrossOrigin或全局CORS配置就万事大吉但实际上Sa-Token的拦截器会在Spring的CORS处理器之前执行导致预检请求preflight被拦截。2. 方案一Sa-Token原生CORS配置推荐这是最符合Sa-Token设计哲学的解决方案。在SaTokenConfig配置类中添加以下代码Configuration public class SaTokenConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .exposedHeaders(Authorization) // 关键暴露Authorization头 .allowCredentials(true) .maxAge(3600); } Bean public SaTokenConfigure saTokenConfigure() { return new SaTokenConfigure() .setIsReadHeader(true) // 开启header读取 .setIsReadCookie(false) // 避免cookie跨域问题 .setTokenName(Authorization); } }避坑指南allowedOriginPatterns比allowedOrigins更灵活支持通配符必须显式暴露Authorization头否则前端无法读取token如果使用cookie传输token需设置allowCredentials(true)且不能使用*作为origin3. 方案二过滤器优先处理方案当项目中有多个拦截器链时可能需要确保CORS处理在最前执行。创建一个优先级最高的过滤器Component Order(Ordered.HIGHEST_PRECEDENCE) public class CorsFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response (HttpServletResponse) res; HttpServletRequest request (HttpServletRequest) req; response.setHeader(Access-Control-Allow-Origin, request.getHeader(Origin)); response.setHeader(Access-Control-Allow-Methods, POST, GET, OPTIONS, DELETE, PUT); response.setHeader(Access-Control-Max-Age, 3600); response.setHeader(Access-Control-Allow-Headers, Authorization, Content-Type, X-Requested-With); response.setHeader(Access-Control-Allow-Credentials, true); if (OPTIONS.equalsIgnoreCase(request.getMethod())) { response.setStatus(HttpServletResponse.SC_OK); } else { chain.doFilter(req, res); } } }实战技巧动态设置Access-Control-Allow-Origin为请求的Origin头比写死*更安全对于OPTIONS预检请求直接返回200避免进入后续拦截链注意header中必须包含Authorization和Content-Type等关键头4. 方案三Nginx层统一处理对于生产环境我更推荐在Nginx层解决跨域问题。以下配置示例可放在server块中location / { if ($request_method OPTIONS) { add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Methods GET, POST, OPTIONS, PUT, DELETE; add_header Access-Control-Allow-Headers Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control; add_header Access-Control-Allow-Credentials true; add_header Access-Control-Max-Age 1728000; add_header Content-Type text/plain; charsetutf-8; add_header Content-Length 0; return 204; } add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Credentials true; add_header Access-Control-Allow-Methods GET, POST, PUT, DELETE, OPTIONS; add_header Access-Control-Allow-Headers Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control; }性能优化建议预检请求的缓存时间Max-Age设置为20天1728000秒减少OPTIONS请求使用$http_origin动态匹配来源比*更安全静态资源可以单独配置更宽松的CORS策略5. 疑难问题排查手册案例1预检请求返回403现象浏览器控制台显示Response to preflight request doesnt pass access control check排查步骤检查Sa-Token版本是否≥1.30.0早期版本有拦截器顺序问题确认没有在拦截器中直接返回response应调用chain.doFilter在SaTokenConfig中设置setIsReadHeader(true)案例2前端无法获取Authorization头现象虽然请求成功但response.headers中看不到token解决方案检查CORS配置中是否有exposedHeaders(Authorization)确保没有重复设置多个CORS配置导致覆盖使用Postman测试确认是浏览器限制问题还是服务端问题案例3带Cookie的请求失败现象控制台提示Credentials mode is include but the Access-Control-Allow-Credentials header is 必须满足服务端设置allowCredentials(true)前端axios设置withCredentials: trueAccess-Control-Allow-Origin不能为*必须明确指定域名6. 进阶Sa-Token SSO中的跨域陷阱在单点登录SSO场景下跨域问题会更加复杂。假设主站是a.com认证中心是sso.com// SSO专属配置 Bean public SaTokenConfigure saTokenConfigure() { return new SaTokenConfigure() .setIsHttp(true) // 启用HTTP模式 .setIsReadHeader(true) .setIsReadCookie(true) .setCookieDomain(.a.com) // 主站顶级域名 .setCookieSameSite(None) // 跨站携带Cookie .setTokenName(satoken); }关键配置说明CookieDomain必须设置为顶级域名如.a.comSameSiteNone需要配合Secure属性HTTPS环境各子系统需要共享Redis作为token存储中心我在实际项目中发现Chrome 80版本的SameSite默认策略变更会导致跨站Cookie失效此时需要后端显式设置SameSiteNone; Secure。