前后端分离架构下,跨域报错是前端联调时最常见的拦路虎,明明接口本地测试正常、后端控制台无异常,前端控制台却疯狂报红,接口请求直接失败、数据无法渲染。这类问题不涉及业务代码,却极易耽误联调进度,新手更是摸不清根源,反复修改配置也无法解决。
✅ 经典CORS报错:No 'Access-Control-Allow-Origin' header is present on the requested resource;
✅ 预检请求失败:OPTIONS请求403/404,正式接口无法调用;
✅ 跨域配置不生效:全局配置、注解配置双双失效;
✅ 自定义请求头跨域失败:token、Authorization等头部无法传递;
✅ 复杂请求跨域失效:POST/PUT/DELETE请求无法正常跨域;
✅ 跨域与拦截器冲突:配置跨域后接口依旧报错。
本篇整理SpringBoot跨域8大高频报错场景 ,从根源讲解跨域原理,每类问题都搭配完整报错原文+核心根因+可直接复制的解决方案,覆盖全局配置、局部配置、避坑优化,不管是简单请求还是复杂请求,照着配置就能彻底解决,建议收藏,联调遇到直接对照!
一、前置科普:什么是跨域?为什么会报错?
浏览器出于安全考虑,遵循同源策略,只有协议、域名、端口三者完全一致,才算同源,不同源之间的请求会被浏览器拦截,这就是跨域。
SpringBoot项目跨域报错,核心原因只有一个:后端未开启CORS跨域支持,未返回对应的跨域响应头,浏览器拦截了请求。后端接口本身正常,只是浏览器的安全限制导致,无需修改业务逻辑,只需配置跨域规则即可解决。
关键区分:简单请求(GET/POST,无自定义请求头)直接触发跨域拦截;复杂请求(PUT/DELETE/自定义头部)会先发起OPTIONS预检请求,预检不通过正式请求直接失败!
二、8大高频跨域报错+完美解决方案
场景1:经典报错 - No 'Access-Control-Allow-Origin' header
1. 前端控制台报错原文
Access to XMLHttpRequest at 'http://localhost:8080/api/user/list' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
2. 核心原因
最基础的跨域问题,后端完全未配置跨域,响应头中缺少跨域必备的Access-Control-Allow-Origin字段,浏览器直接拦截请求。
3. 解决方案(全局跨域配置,推荐)
新建配置类,实现WebMvcConfigurer接口,全局开启跨域,适配所有接口:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 匹配所有接口
.allowedOriginPatterns("*") // 允许所有域名,生产可指定具体域名
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 允许请求方式
.allowCredentials(true) // 允许携带cookie、token等凭证
.allowedHeaders("*") // 允许所有请求头
.maxAge(3600); // 预检请求有效期,单位秒
}
}
场景2:OPTIONS预检请求403/404报错
1. 典型现象
PUT、DELETE、带自定义请求头的接口调用失败,前端控制台显示OPTIONS请求403 Forbidden或404 Not Found。
2. 核心原因
复杂请求会先发起OPTIONS预检请求,后端跨域配置未放行OPTIONS请求,或拦截器、权限框架拦截了预检请求,导致预检失败。
3. 解决方案
-
确保跨域配置中包含OPTIONS请求(参考场景1配置);
-
拦截器、权限框架(如Security、Sa-Token)放行OPTIONS请求:
// 拦截器放行OPTIONS请求示例
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 放行预检请求
if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
return true;
}
// 原有拦截逻辑
return true;
}
场景3:跨域配置与SpringSecurity冲突,配置失效
1. 典型现象
单独配置跨域正常,集成SpringSecurity后,跨域报错重新出现,配置完全不生效。
2. 核心原因
SpringSecurity过滤器优先级高于跨域配置,请求先被Security拦截,跨域配置未生效,需在Security中开启跨域支持。
3. 解决方案
在Security配置类中开启跨域,整合跨域配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
// 开启跨域,复用自定义CorsConfig
.cors().and()
// 关闭csrf防护
.csrf().disable()
// 其他权限配置
.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
return http.build();
}
}
场景4:@CrossOrigin局部注解失效
1. 典型现象
在Controller或接口上添加@CrossOrigin注解,依旧报跨域错误。
2. 核心原因
-
注解属性配置错误,未放行对应请求;
-
全局跨域与局部注解冲突;
-
拦截器、权限框架拦截了请求。
3. 解决方案
规范使用@CrossOrigin注解,适配所有跨域场景:
// 控制器类上添加,适配所有接口
@RestController
@RequestMapping("/api/user")
@CrossOrigin(originPatterns = "*", allowCredentials = "true", allowedHeaders = "*", methods = {RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.OPTIONS})
public class UserController {
// 接口代码
}
// 单个接口上添加
@GetMapping("/list")
@CrossOrigin
public Result getUserList() {
return Result.success();
}
场景5:携带token/自定义请求头跨域失败
1. 典型现象
普通接口跨域正常,携带token、Authorization等自定义请求头后,跨域报错重现。
2. 核心原因
跨域配置未放行自定义请求头,浏览器拦截携带自定义头部的请求。
3. 解决方案
修改全局跨域配置,明确允许自定义请求头,或直接放行所有请求头:
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowCredentials(true)
// 放行所有请求头,包含自定义token
.allowedHeaders("*")
.exposedHeaders("Authorization", "token") // 暴露自定义响应头
.maxAge(3600);
}
场景6:allowCredentials与allowedOrigin冲突报错
1. 前端控制台报错原文
Access to XMLHttpRequest at 'http://localhost:8080/api/user/list' from origin 'http://localhost:8081' has been blocked by CORS policy: The value of 'Access-Control-Allow-Origin' cannot be the wildcard '*' when the request's credentials mode is 'include'.
2. 核心原因
开启allowCredentials(true)允许携带凭证后,不能使用allowedOrigins("*")通配符,必须指定具体域名。
3. 解决方案
将allowedOrigins替换为allowedOriginPatterns,即可兼容通配符与凭证携带:
// 错误写法
// .allowedOrigins("*")
// 正确写法
.allowedOriginPatterns("*")
场景7:跨域配置后响应头缺失,依旧报错
1. 典型现象
配置了跨域,但响应头中依旧没有Access-Control-Allow-Origin字段,浏览器依旧拦截。
2. 核心原因
-
跨域配置类未被Spring加载(漏加@Configuration注解);
-
项目存在多个跨域配置,互相覆盖;
-
过滤器手动清空了响应头。
3. 解决方案
-
检查配置类必须添加@Configuration注解;
-
删除多余跨域配置,保留一套全局配置;
-
排查过滤器,避免手动清除跨域响应头。
场景8:网关(Gateway)整合后跨域重复报错
1. 典型现象
微服务项目通过Gateway网关调用,配置网关跨域后,依旧报重复跨域头错误。
2. 核心原因
网关和微服务都配置了跨域,导致响应头重复,浏览器识别异常。
3. 解决方案
微服务项目只在网关层配置跨域,删除所有微服务自身的跨域配置,避免重复配置。
三、跨域万能排查步骤
-
查看前端报错,定位是Origin缺失、预检失败还是凭证冲突;
-
检查全局跨域配置,确保注解、属性配置无误;
-
排查拦截器、权限框架,放行OPTIONS预检请求;
-
微服务项目只保留网关一层跨域配置;
-
查看接口响应头,确认跨域字段是否正常返回。
四、生产环境跨域避坑指南
-
生产环境禁止使用allowedOriginPatterns("*"),指定具体前端域名,提升安全性;
-
优先使用全局跨域配置,避免局部注解零散管理;
-
集成权限框架后,必须同步适配跨域配置,避免过滤器优先级冲突;
-
复杂请求务必放行OPTIONS预检请求,否则正式请求无法发起;
-
微服务架构只在网关配置跨域,微服务自身禁止配置跨域;
-
避免同时使用多种跨域配置方式,防止互相冲突。
五、总结
SpringBoot跨域报错,看似问题繁杂,实则都是配置缺失、配置冲突、权限拦截三大类问题。只要理清跨域原理,统一使用全局跨域配置,适配权限框架与微服务架构,就能彻底解决所有跨域问题。
前后端联调遇到跨域不用慌,对照本文对应场景,复制对应配置,一分钟即可解决,再也不用为跨域问题耽误开发进度。
如果这篇文章帮到你了,记得点赞+收藏🌟!评论区说说你踩过的跨域坑,一起交流避坑~