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

Vue3 + Spring Boot 项目中跨域问题的排查与解决

前言

作为一名普通的程序开发者,日常开发中经常会遇到各种奇怪的问题。今天我来分享一个在 Vue3 和 Spring Boot 混合开发项目中遇到的真实跨域问题。这个问题看似简单,但实际排查过程却让我花了不少时间。本文将从问题现象、分析思路、排查步骤到最终解决方案,一步步还原整个调试过程。

问题现象

在我们团队的一个前后端分离项目中,前端使用的是 Vue3,后端是 Spring Boot。正常情况下,前端通过 axios 调用后端接口应该能成功获取数据。但在某次更新之后,发现某些接口调用失败,浏览器控制台提示如下错误:

Access to fetch at 'http://api.example.com/data' from origin 'http://localhost:8081' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

起初我以为是后端配置出了问题,但查看了 Spring Boot 的相关配置,发现已经添加了 @CrossOrigin 注解,并且也设置了 spring.mvc.cors.allowed-origins。然而问题依旧存在,这就让人感到困惑了。

问题分析

首先,我回顾一下 Vue3 和 Spring Boot 的通信机制。前端通过 axios 发送请求,后端通过 Spring Boot 提供 REST 接口。跨域问题是由于浏览器的安全策略导致的,只有当后端返回的响应头中包含 Access-Control-Allow-Origin 字段时,浏览器才会允许该请求。

可能的原因包括:

  • 后端没有正确设置 CORS 配置
  • 前端请求的域名和后端配置的允许域名不一致
  • 请求方式或请求头不符合 CORS 规范
  • 使用了代理服务器,但未正确配置

排查步骤

1. 检查后端 CORS 配置

首先确认后端是否真的启用了 CORS 支持。我们在 Spring Boot 中通常有两种方式启用 CORS:

方式一:使用 @CrossOrigin 注解
@RestController
@RequestMapping("/api")
@CrossOrigin(origins = "http://localhost:8081")
public class DataController {@GetMapping("/data")public ResponseEntity<String> getData() {return ResponseEntity.ok("Hello from backend!");}
}
方式二:全局配置
@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/api/**").allowedOrigins("http://localhost:8081").allowedMethods("GET", "POST").allowedHeaders("*").exposedHeaders("Access-Control-Allow-Origin").maxAge(3600).allowCredentials(true);}
}

但即使这样,仍然无法解决问题,说明可能还有其他问题。

2. 使用 Postman 测试接口

为了排除前端问题,我尝试使用 Postman 直接访问后端接口,结果发现接口可以正常返回数据,说明后端逻辑没问题。这说明问题出在浏览器的 CORS 策略上。

3. 检查前端请求配置

在 Vue3 中,我们使用 axios 发送请求,代码如下:

import axios from 'axios';const apiClient = axios.create({baseURL: 'http://api.example.com',timeout: 5000,
});export default {async fetchData() {try {const response = await apiClient.get('/data');console.log(response.data);} catch (error) {console.error('Error fetching data:', error);}},
};

看起来没有问题,但问题还是存在。

4. 检查浏览器控制台输出

再次打开浏览器控制台,发现除了之前的错误信息外,还有一条额外的信息:

Request URL: http://api.example.com/data
Request Method: GET
Status Code: 200 OK
Remote Address: 127.0.0.1:8080
Referrer Policy: no-referrer-when-downgrade

但是,响应头中并没有 Access-Control-Allow-Origin 字段。这说明后端虽然配置了 CORS,但实际上没有生效。

5. 检查后端日志

查看 Spring Boot 应用的日志,发现确实有请求到达,但没有看到任何关于 CORS 的日志。这说明可能是 Spring Boot 的 CORS 配置没有被正确加载。

6. 检查 Spring Boot 的依赖和版本

发现我们的项目中使用的是 Spring Boot 2.6.x,而有些 CORS 相关的类在较新的版本中发生了变化。我们尝试升级到 Spring Boot 2.7.x,问题依然存在。

7. 检查是否使用了反向代理

我们项目中使用 Nginx 作为反向代理。检查 Nginx 配置文件,发现没有设置 Access-Control-Allow-Origin 头,因此导致浏览器认为请求被拦截。

8. 修改 Nginx 配置

在 Nginx 配置中添加以下内容:

location /api {proxy_pass http://localhost:8080;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Max-Age' 1728000;add_header 'Content-Type' 'text/plain; charset=utf-8';add_header 'Content-Length' 0;
}

保存并重启 Nginx 后,问题终于也是完美解决

总结

这次跨域问题虽然看似简单,但排查过程却非常复杂。从后端配置到前端请求,再到反向代理的设置,每一个环节都可能成为问题的根源。通过逐步排查,最终找到了问题所在——Nginx 没有正确设置 CORS 头。

对于类似的问题,建议在开发过程中尽早测试接口,避免后期出现难以定位的问题。同时,合理配置反向代理也是确保前后端分离项目顺利运行的重要一步。

http://www.xdnf.cn/news/1389601.html

相关文章:

  • CS144 lab3 tcp_sender
  • 自动驾驶中的传感器技术36——Lidar(11)
  • 《生成式AI消费级应用Top 100——第五版》| a16z
  • uni-app 跨平台项目的 iOS 上架流程:多工具组合的高效协作方案
  • driver.js实现前端页面引导
  • 【Flask】测试平台开发,集成禅道
  • 渗透测试学习笔记
  • dm8_静默安装简单快速
  • 基于EB的K3XX_GPT定时器中断的实现方法
  • 音视频直播卡顿分析与优化:技术原理、实践案例与未来趋势
  • Java 流(Stream)、文件(File)和IO
  • 基于 Python asyncio 和币安 WebSocket 打造高频加密货币预警机器人
  • 【Spring Cloud Alibaba】前置知识
  • 订餐后台项目-day02数据库模型定义笔记
  • 从0开始学习Java+AI知识点总结-28.Linux部署
  • Java 8核心特性详解:从Lambda到Stream的革命性升级
  • lesson49:HTML基础标签全解析:从入门到精通的网页构建指南
  • SQL Server 查看备份计划
  • Cursor不能读取.env文件解决办法(**/.env、**/env.*)
  • 华为认证全解析:价值详解、含金量解读(2025最新版)
  • 安全月报 | 傲盾DDoS攻击防御2025年8月简报
  • CRYPT32!CryptMsgUpdate函数分析之CRYPT32!PkiAsn1Decode函数的作用是得到pci
  • 达梦数据库-归档日志(一)
  • JavaScript 入门教程
  • 《Linux 网络编程六:数据存储与SQLite应用指南》
  • TF-IDF:文本分析的“火眼金睛”
  • PCIe 6.0 TLP路由机制:解密高效数据传输的核心架构
  • 【微知】如何撤销一个git的commit?以及撤销的3种方式?
  • 在本地获取下载chrome,然后离线搬运到 ECS
  • 最小生成树——Kruskal