在前后端分离开发模式中,跨域问题是联调阶段最常见、最容易卡进度的问题之一。前面我们完成了接口开发、全局异常处理、参数校验、接口日志统一打印等基础能力搭建,项目接口已经具备完整的业务能力和问题排查能力。但一旦前端通过Vue、React等框架独立部署访问后端接口,浏览器就会触发CORS跨域拦截,出现控制台报跨域错误、请求无响应、预检请求失败、403跨域拒绝等问题,导致前后端完全无法联调。

很多新手解决跨域只会简单使用注解或者配置通配符,看似临时解决问题,却会埋下大量线上隐患:生产环境跨域失效、携带Token请求报错、PUT/DELETE请求拦截、SpringSecurity冲突、多配置优先级混乱等。本文将从跨域核心原理入手,讲解企业级标准的全局跨域配置方案,对比多种配置方式的优劣,重点梳理前后端联调的高频坑点与解决方案,适配Spring Boot2.x、3.x全版本,一套配置适配开发、测试、生产全环境,彻底根治跨域问题。
跨域全称跨域资源共享(CORS),是浏览器为了防范恶意网站窃取数据的安全同源策略限制。浏览器规定:只有协议、域名、端口三者完全一致,才属于同源请求,允许正常访问接口;任意一个要素不同,即判定为跨域请求,浏览器会拦截响应数据。
前后端分离项目天然存在跨域场景:前端本地运行在 http://localhost:8080,后端接口运行在 http://localhost:8088,端口不一致,直接触发跨域拦截。需要注意的是:跨域是浏览器的限制,和后端服务无关,后端接口本身已经正常执行,只是浏览器拒绝接收响应结果。
浏览器将跨域请求分为两类,不同请求的跨域校验规则完全不同,绝大多数联调报错都源于对这两种请求的认知缺失:
1. 简单请求
仅支持 GET、POST、HEAD 三种请求方式,且请求头仅包含基础字段、无自定义请求头、无复杂请求体。简单请求不会发送预检请求,浏览器直接发起接口请求,通过响应头判断是否允许跨域。
2. 预检请求(OPTIONS请求)
PUT、DELETE 请求、携带 Token 自定义请求头、复杂JSON请求体等场景,都会触发预检请求。浏览器会先发送一次 OPTIONS 预检请求,询问后端是否允许当前跨域请求,预检通过后,才会发起真正的业务请求。若后端未处理 OPTIONS 请求,会直接跨域报错,业务请求无法执行。
同时 Spring Boot 3.x 对预检请求规则大幅收紧,旧版本默认兼容所有请求方法,3.x 版本默认仅允许 GET、POST、HEAD,若未手动配置 PUT、DELETE 方法,会直接拦截请求,这是高版本项目跨域失效的核心原因之一。
Spring Boot 提供多种跨域解决方案,不同方案适配场景、优先级、稳定性差异极大,新手极易混用导致冲突。这里对四种主流方案做完整对比,帮助大家按需选择:
直接在 Controller 类或接口方法上添加注解,仅对当前类/接口生效,优点是使用简单、按需开启,缺点是配置分散、无法统一管理、后期维护成本极高,大型项目不推荐使用。同时该注解和全局配置混用会出现优先级混乱,导致跨域规则失效。
通过注册 CorsFilter 过滤器统一拦截所有请求,配置集中、优先级高,适配所有版本 Spring Boot,兼容性极强,适合需要精细控制跨域规则、整合权限框架的项目。
实现 WebMvcConfigurer 接口,重写跨域方法,全局统一配置所有接口跨域规则,代码简洁、无侵入、便于维护,是绝大多数前后端分离项目的标准方案,本文重点主推该方案。
Spring Boot2.4+ 支持直接在 yml 配置文件配置跨域,无需编写代码,极简高效,但灵活性较低,无法适配复杂场景(多域名、动态域名、自定义请求头),仅适合小型简单项目。
本文提供两套最稳定的全局跨域方案,适配不同项目场景,二选一使用,禁止混用,彻底避免配置冲突问题。所有代码均删除导包语句,直接复制即可使用。
该方案集中管理所有跨域规则,支持多域名、通配符域名、所有请求方法、携带Cookie与Token,自动处理OPTIONS预检请求,适配Spring Boot2.x、3.x全版本,是企业项目通用标准配置。
// 全局跨域配置类(统一解决前后端跨域问题)
@Configuration
public class CorsConfig implements WebMvcConfigurer {
/**
* 全局跨域规则配置
* 适配所有接口、所有前端域名、所有请求方式,支持Token、Cookie跨域传递
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
// 适配多环境前端域名,支持通配符匹配
.allowedOriginPatterns("http://localhost:*", "http://127.0.0.1:*")
// 放行所有业务请求方法 + OPTIONS预检请求
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
// 放行所有自定义请求头(适配Token、自定义参数头)
.allowedHeaders("*")
// 允许跨域携带Cookie、Token凭证(核心配置)
.allowCredentials(true)
// 预检请求缓存时长(1小时,减少重复预检请求,提升联调效率)
.maxAge(3600);
}
}
核心配置详解:
无需编写Java代码,仅通过yml配置文件快速开启跨域,适配Spring Boot2.4及以上版本,简单高效,适合功能简单、无需复杂跨域规则的项目。
# 全局跨域配置(Spring Boot2.4+ 专属)
spring:
web:
cors:
# 允许的前端域名(多域名用逗号分隔)
allowed-origins: http://localhost:8080,http://127.0.0.1:8080
# 允许的请求方法
allowed-methods: GET,POST,PUT,DELETE,OPTIONS
# 允许携带凭证
allow-credentials: true
# 预检请求缓存时间
max-age: 3600
# 允许所有请求头
allowed-headers: "*"
若项目集成了SpringSecurity权限框架,普通WebMvc跨域配置会失效,必须使用过滤器方式配置跨域,否则预检请求会被安全框架拦截,联调必报错。
// SpringSecurity适配跨域配置
@Configuration
public class SecurityCorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 允许跨域域名
config.setAllowedOriginPatterns("http://localhost:*", "http://127.0.0.1:*");
// 允许请求方法
config.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE","OPTIONS"));
// 允许请求头
config.setAllowedHeaders(Arrays.asList("*"));
// 允许凭证传递
config.setAllowCredentials(true);
// 预检缓存时间
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}
大部分跨域报错并非配置未生效,而是配置不规范、版本不兼容、前后端参数不匹配导致。下面整理联调过程中99%开发者都会遇到的坑点,附带完整解决方案。
报错现象:开启凭证跨域后,使用 allowedOrigins(“*”) 全局放行域名,浏览器直接报跨域错误,无法携带Token。
原因:浏览器安全规范禁止 允许凭证 + 任意域名 同时生效,认为该组合存在极大安全风险,Spring Boot高版本直接拦截该配置。
解决方案:放弃 allowedOrigins 通配符,使用 allowedOriginPatterns 支持通配符匹配,完美兼容凭证跨域,也是目前官方推荐写法。
报错现象:普通查询、新增接口正常,修改、删除接口直接跨域,无业务日志输出。
原因:PUT/DELETE请求触发浏览器OPTIONS预检请求,项目未配置放行OPTIONS方法,预检请求拦截,导致真实请求无法发起;Spring Boot3.x默认仅放行GET、POST、HEAD,未手动配置会直接拦截。
解决方案:跨域配置中主动添加 OPTIONS 请求方法,全局放行预检请求。
报错现象:部分接口跨域正常,部分接口随机报错,规则混乱、难以排查。
原因:注解跨域和全局跨域配置优先级不统一,相互覆盖,导致跨域规则错乱。
解决方案:项目统一使用全局跨域配置,删除所有接口上的@CrossOrigin注解,配置集中统一管理,杜绝冲突。
报错现象:不带Token的普通请求正常,登录后携带Token请求直接跨域。
原因:未开启allowCredentials凭证跨域,或未放行自定义Authorization请求头,浏览器拦截带凭证的跨域请求。
解决方案:开启allowCredentials=true,同时通过allowedHeaders放行所有自定义请求头,确保Token可以正常传递。
报错现象:本地联调完全正常,部署服务器后前端页面跨域报错。
原因:全局配置仅放行localhost、127.0.0.1本地域名,未配置生产环境前端正式域名;生产环境前后端域名、端口不一致,触发跨域拦截。
解决方案:在allowedOriginPatterns中添加生产前端域名,支持多域名配置,适配多环境部署。
报错现象:普通接口跨域正常,需要登录认证的接口跨域报错,控制台403。
原因:SpringSecurity权限框架优先级高于WebMvc跨域配置,预检请求未携带Token,被安全拦截器拦截,导致跨域失效。
解决方案:使用CorsFilter过滤器方式配置跨域,同时在Security配置中开启跨域支持,确保安全框架放行跨域请求。
为彻底避免联调阶段反复踩坑,整理一套标准化联调流程,适配所有前后端分离项目:
跨域问题本质不是Bug,而是浏览器的安全限制,绝大多数联调跨域报错,都是配置不规范、版本不兼容、场景适配缺失导致。本文提供的三套全局跨域方案,覆盖简单项目、通用项目、权限项目全场景,彻底替代零散的注解配置。
核心避坑要点:统一全局配置、禁止多方案混用、务必放行OPTIONS预检请求、开启凭证跨域适配Token登录、区分Spring Boot版本差异、适配多环境域名。将该全局配置集成到项目中,可彻底解决前后端联调所有跨域问题,保证项目从开发到上线全程稳定可用。