spring mvc解决跨域的核心是后端通过响应头明确声明允许的源、方法、请求头及凭证策略;主流配置方式有三种:全局配置(webmvcconfigurer)、控制器粒度配置(@crossorigin注解)和xml/filter手动配置,其中全局配置最常用且推荐,需注意allowcredentials与allowedorigins冲突、预检请求处理及spring security对options的拦截等关键坑点。

Spring MVC 解决前后端分离项目的跨域访问,核心是让后端明确告诉浏览器:“哪些前端域名可以访问我,允许带什么头、什么方法、是否传 Cookie”。配置方式有三种主流路径,按推荐度和适用场景区分,不复杂但容易忽略关键细节。
全局配置:用 WebMvcConfigurer 统一管理(最常用)
适合绝大多数前后端分离项目,集中控制、逻辑清晰、便于维护。
- 创建配置类实现 WebMvcConfigurer 接口,重写 addCorsMappings 方法
- 路径匹配建议用 /api/** 或 /**,避免过度开放(如只开放接口路径,不开放静态资源)
-
allowedOrigins 生产环境必须写具体域名,比如
["https://admin.example.com", "https://app.example.com"];开发阶段可用 allowedOriginPatterns 配合通配符,如"http://localhost:*" - 若前端需携带 Cookie 或 Token(如 JWT 存于 Cookie),allowCredentials 必须设为 true,且此时 allowedOrigins 不能用 *,否则浏览器会拒绝
-
allowedHeaders 建议明确列出,如
"Content-Type, Authorization, X-Requested-With";设为"*"在部分旧浏览器或严格模式下可能被忽略
控制器粒度配置:用 @CrossOrigin 注解(最灵活)
适合局部放开跨域,比如某个接口要对接第三方系统,或测试阶段快速验证。
Java Linux版下载入口,提供 Oracle JDK 26.0.2 官方 Linux 安装包、Java 环境配置、JDBC 数据库连接和 Java 服务端开发相关信息。
- 加在 Controller 类上,作用于全部接口;加在具体方法上,只对该接口生效
- 支持细粒度控制:可单独指定 origins、methods、maxAge、allowCredentials
- 例如:
@CrossOrigin(origins = "https://test-site.com", allowCredentials = "true") - 注意:若同时存在全局配置和注解配置,注解配置优先级更高,会覆盖全局规则
XML 配置或 Filter 手动设置(兼容老项目)
适用于 Spring MVC 传统 XML 配置项目,或需要完全自定义响应头的特殊场景(如动态 Origin 判断)。
- XML 方式(Spring 4.2+):在
spring-mvc.xml中使用<cors></cors>标签,结构清晰但灵活性低 - Filter 方式:自定义 Filter,在
doFilter中手动设置响应头,如response.setHeader("Access-Control-Allow-Origin", origin) - Filter 的优势是可以读取请求头动态决定 Origin(比如从请求参数或数据库查白名单),但需自行处理预检请求(OPTIONS)返回 200,否则复杂请求会失败
- 缺点是绕过了 Spring 的 CORS 管理机制,无法享受自动预检响应、异常统一处理等特性
必须注意的几个坑
很多跨域问题不是没配,而是配得“差不多但差一点”:
-
Credentials 和 Origin 冲突:设置了
allowCredentials=true却还用allowedOrigins=["*"],浏览器直接报错 - 预检失败静默无提示:非简单请求(如带自定义 header 或 Content-Type: application/json)会先发 OPTIONS 请求;若后端没正确响应 200 + 对应头,前端只显示 “Network Error” 或 “CORS error”,看不到真实原因
- 多个配置叠加失效:比如同时用了全局配置 + @CrossOrigin + Filter,容易互相覆盖或重复添加头,导致响应头冲突(如两个 Access-Control-Allow-Origin)
-
Spring Security 默认拦截 OPTIONS:如果项目集成了 Spring Security,它可能把预检请求当成未认证请求拦掉,需显式放行:
http.authorizeHttpRequests(auth -> auth.requestMatchers(HttpMethod.OPTIONS, "/api/**").permitAll())
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










