当前位置: 首页 > news >正文

SpringBoot跨域报错全集|CORS、OPTIONS预检、无Access-Control报错全解决

前后端分离架构下,跨域报错是前端联调时最常见的拦路虎,明明接口本地测试正常、后端控制台无异常,前端控制台却疯狂报红,接口请求直接失败、数据无法渲染。这类问题不涉及业务代码,却极易耽误联调进度,新手更是摸不清根源,反复修改配置也无法解决。

✅ 经典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. 解决方案

  1. 确保跨域配置中包含OPTIONS请求(参考场景1配置);

  2. 拦截器、权限框架(如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. 解决方案

  1. 检查配置类必须添加@Configuration注解;

  2. 删除多余跨域配置,保留一套全局配置;

  3. 排查过滤器,避免手动清除跨域响应头。

场景8:网关(Gateway)整合后跨域重复报错

1. 典型现象

微服务项目通过Gateway网关调用,配置网关跨域后,依旧报重复跨域头错误。

2. 核心原因

网关和微服务都配置了跨域,导致响应头重复,浏览器识别异常。

3. 解决方案

微服务项目只在网关层配置跨域,删除所有微服务自身的跨域配置,避免重复配置。

三、跨域万能排查步骤

  1. 查看前端报错,定位是Origin缺失、预检失败还是凭证冲突;

  2. 检查全局跨域配置,确保注解、属性配置无误;

  3. 排查拦截器、权限框架,放行OPTIONS预检请求;

  4. 微服务项目只保留网关一层跨域配置;

  5. 查看接口响应头,确认跨域字段是否正常返回。

四、生产环境跨域避坑指南

  • 生产环境禁止使用allowedOriginPatterns("*"),指定具体前端域名,提升安全性;

  • 优先使用全局跨域配置,避免局部注解零散管理;

  • 集成权限框架后,必须同步适配跨域配置,避免过滤器优先级冲突;

  • 复杂请求务必放行OPTIONS预检请求,否则正式请求无法发起;

  • 微服务架构只在网关配置跨域,微服务自身禁止配置跨域;

  • 避免同时使用多种跨域配置方式,防止互相冲突。

五、总结

SpringBoot跨域报错,看似问题繁杂,实则都是配置缺失、配置冲突、权限拦截三大类问题。只要理清跨域原理,统一使用全局跨域配置,适配权限框架与微服务架构,就能彻底解决所有跨域问题。

前后端联调遇到跨域不用慌,对照本文对应场景,复制对应配置,一分钟即可解决,再也不用为跨域问题耽误开发进度。

如果这篇文章帮到你了,记得点赞+收藏🌟!评论区说说你踩过的跨域坑,一起交流避坑~

http://www.jsqmd.com/news/568060/

相关文章:

  • nlp_structbert_sentence-similarity_chinese-large入门指南:从ModelScope下载到本地Web服务上线
  • FPGA流水线设计避坑指南:时序问题与数据匹配的5个常见错误
  • 突破方舟生存进化技术壁垒的智能管理工具
  • ISAAC Sim 5.0在Win10上的性能优化:如何加速编译和启动过程
  • 保姆级教程:用StarRocks Profile和Explain功能排查数据倾斜问题
  • 胜宏科技通过上市聆讯:2025年营收193亿 净利43亿 刚定增募资19亿
  • 别再死记硬背!用Python+OpenCV手把手带你搞定直方图均衡化(附完整代码与避坑指南)
  • 解决EDK2编译中BrotliCompress.c头文件缺失问题的实战指南
  • 终极Windows驱动管家:DriverStore Explorer释放系统空间完全指南
  • TCP粘包/半包问题终结方案:基于Java NIO+Protocol Buffers的协议解析工具链(含完整Spring Boot Starter开源实践)
  • 实测对比:飞算JavaAI vs Copilot,效率差距让我决定转投
  • 用快马AI三分钟搞定网页转打印文档,告别手动复制粘贴
  • Go 语言并发编程:Goroutine 与 Channel 实战指南
  • 镜像视界(浙江)科技有限公司核心技术模块体系——构建“像素即坐标”的空间智能操作系统(SpaceOS)
  • Wan2.2-I2V-A14B部署教程:RTX 4090D显卡下WebUI界面配置与参数详解
  • Graphormer在金属有机框架(MOF)预测中的拓展应用:配体性质建模
  • YOLO 系列专栏(二十八)番外:PKINet 改进 YOLO26 主干,遥感目标检测高效涨点方案
  • Element Plus访问优化指南:从卡顿到流畅的开发体验提升方案
  • Spring_couplet_generation 与低代码平台Dify结合:可视化构建春联应用
  • STM32 SRAM调试实战与优化技巧
  • Linux命令-mv(移动或重命名文件和目录)
  • DOL-CHS-MODS:一站式革新游戏体验的汉化美化整合方案
  • 快速原型实践:用快马平台十分钟搭建7446ccn资料大全更新日志页面
  • FPGA设计避坑:Vivado 2023.1中Complex Multiplier IP核的AXI4数据对齐与位宽处理实战
  • 【独家首发】基于eBPF+Java Agent+Istio Telemetry V2的零侵入式调试框架(已落地金融级生产环境,QPS>50K场景验证)
  • MiniCPM-V-2_6国产多模态突破:开源可部署+多语言+低幻觉实战手册
  • 7个高效步骤:Meshroom开源三维重建工具从入门到精通
  • 抖音无水印批量下载完全指南:5个专业级技巧助你高效管理视频资源
  • 小白友好!MogFace本地部署全攻略,从安装到检测只需3步
  • ewgui:面向嵌入式C++的emWin轻量级面向对象封装