前后端跨域处理全指南:Java 后端(Spring Boot) + Vue 前端 完整解决方案(2026 最新版)
跨域(CORS)是前后端分离项目中最常见的问题之一。本文从原理到实战,系统性给出 Java Spring Boot + Vue 3(Vite) 的最优解决方案。
一、跨域到底是什么?为什么会出现?
同源策略(Same-Origin Policy)是浏览器最核心的安全策略。
同源 = 协议 + 域名 + 端口 三者完全相同。
示例:
- 前端:
http://localhost:5173(Vite 默认端口) - 后端:
http://localhost:8080
→ 不同源 → 浏览器默认阻止前端发起的请求(除了 <img>、<script>、<link> 等标签)。
跨域错误典型提示:
Access to XMLHttpRequest at 'http://localhost:8080/api/login'
from origin 'http://localhost:5173' has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
二、CORS 工作原理(必须理解)
CORS 分两种请求:
- 简单请求(Simple Request)
- 方法:GET、POST、HEAD
- 头信息:
Accept、Content-Type: text/plain、multipart/form-data、application/x-www-form-urlencoded - 浏览器直接发送,服务器返回
Access-Control-Allow-Origin即可
- 预检请求(Preflight / OPTIONS)
- 复杂请求(PUT、DELETE、自定义头、Content-Type: application/json 等)
- 浏览器先发 OPTIONS 请求询问服务器是否允许
- 服务器返回允许信息后,才发真实请求
关键响应头(后端必须返回):
| 响应头 | 作用 | 推荐值 |
|---|---|---|
| Access-Control-Allow-Origin | 允许的源 | *(开发)或具体域名 |
| Access-Control-Allow-Methods | 允许的请求方法 | GET, POST, PUT, DELETE, OPTIONS |
| Access-Control-Allow-Headers | 允许的自定义请求头 | Content-Type, Authorization, X-Requested-With |
| Access-Control-Allow-Credentials | 是否允许携带 Cookie | true(需要时) |
| Access-Control-Max-Age | 预检请求缓存时间(秒) | 3600(1小时) |
三、后端解决方案(Spring Boot 3.x 推荐顺序)
推荐方案一:全局 CorsFilter(最灵活,强烈推荐)
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 允许所有域名(生产环境建议改成具体域名)
config.addAllowedOriginPattern("*"); // Spring Boot 2.4+ 推荐
// config.setAllowedOriginPatterns(Arrays.asList("http://localhost:5173", "https://yourdomain.com"));
config.addAllowedMethod("*"); // 允许所有方法
config.addAllowedHeader("*"); // 允许所有头
config.setAllowCredentials(true); // 允许携带 Cookie(重要!)
config.setMaxAge(3600L); // 预检缓存 1 小时
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config); // 所有接口
return new CorsFilter(source);
}
}
推荐方案二:WebMvcConfigurer(Spring Boot 官方推荐方式)
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
方案三:单个接口使用注解(适合临时测试)
@CrossOrigin(
origins = "http://localhost:5173",
allowCredentials = "true",
maxAge = 3600
)
@RestController
@RequestMapping("/api")
public class UserController { ... }
四、前端 Vue 解决方案(Vite 项目)
开发环境(强烈推荐)—— 使用代理(最简单)
Vite 项目(vite.config.js 或 vite.config.ts):
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
server: {
port: 5173,
proxy: {
'/api': { // 所有 /api 开头的请求都会被代理
target: 'http://localhost:8080',
changeOrigin: true, // 必须
rewrite: (path) => path.replace(/^\/api/, '/api') // 可根据需要改写
}
}
}
})
Vue CLI 项目(vue.config.js):
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true,
pathRewrite: { '^/api': '' }
}
}
}
}
生产环境处理
- 推荐:后端统一返回 CORS 头(上面 CorsFilter 或 WebMvcConfigurer)
- 备选:Nginx / API 网关(如 Spring Cloud Gateway、Kong)统一处理跨域
- 不推荐:前端在生产环境继续使用代理(vite proxy 只在开发环境生效)
五、携带 Cookie / Token 的跨域配置(重要!)
当需要携带认证信息时,必须同时满足:
后端:
config.setAllowCredentials(true);
config.addAllowedOriginPattern("https://yourdomain.com"); // 不能用 *
前端 axios 配置(推荐):
import axios from 'axios'
const service = axios.create({
baseURL: '/api', // 配合代理使用
timeout: 15000,
withCredentials: true // 关键!允许携带 Cookie
})
六、生产环境最佳实践(推荐架构)
- 开发环境:前端 Vite 代理(最方便调试)
- 测试/生产环境:
- 后端 Spring Boot 统一开启 CORS(使用 CorsFilter)
- 或在 Nginx / Gateway 层统一处理跨域(更推荐)
- 域名分离:
api.yourdomain.com(后端) +www.yourdomain.com(前端)
Nginx 示例:
location /api/ {
proxy_pass http://backend:8080;
add_header 'Access-Control-Allow-Origin' '$http_origin';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' '*';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 3600;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
七、常见问题排查清单
- 后端返回了
*但前端withCredentials: true→ 报错 - 使用了
allowedOrigins而不是allowedOriginPatterns(Spring Boot 2.4+ 变更) - OPTIONS 请求被拦截或返回 403/405
- 多层代理(Nginx + Spring Gateway)导致 Origin 被覆盖
- 前端请求路径写错(
/apivs/api/)
调试技巧:
- Chrome 开发者工具 → Network → 查看请求的 Response Headers
- 重点检查
Access-Control-Allow-Origin、Access-Control-Allow-Credentials
总结:推荐组合方案
- 开发阶段:前端 Vite 代理(最快)
- 生产阶段:后端 Spring Boot + CorsFilter(或 Nginx 统一处理)
- 认证场景:必须同时开启
allowCredentials(true)+withCredentials: true+ 指定具体域名
需要我给你完整可运行的 Spring Boot + Vue 3 项目模板(包含 CorsFilter + axios 配置 + Token 拦截器)吗?可以直接发你。