跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Java大前端java

前后端跨域处理全指南:Java 后端+Vue 前端完整解决方案

跨域问题成因及浏览器同源策略,提供 Java 后端与 Vue 前端的六种跨域解决方案。包括 @CrossOrigin 注解、全局 CORS 配置、过滤器、Spring Security 集成、Vue 开发代理及 Nginx 反向代理。涵盖代码示例、优缺点分析及最佳实践建议,解决生产环境部署中的常见问题如预检请求失败、Cookie 携带等,适用于初中级开发者参考。

修罗发布于 2026/4/6更新于 2026/7/2358 浏览

前后端跨域处理全指南:Java 后端+Vue 前端完整解决方案

一、跨域基础概念

1.1 什么是跨域?

跨域(Cross-Origin)是指浏览器出于安全考虑,限制从一个域(协议 + 域名 + 端口)加载的网页去请求另一个域的资源。当协议、域名或端口三者中有任意一项不同时,就会触发跨域限制。

示例:

  • http://localhost:3000 → http://localhost:8080(端口不同)❌ 跨域
  • http://example.com → https://example.com(协议不同)❌ 跨域
  • http://api.example.com → http://www.example.com(子域名不同)❌ 跨域
  • http://localhost:3000 → http://localhost:3000/api(同源)✅ 不跨域

1.2 为什么会有跨域限制?

浏览器的同源策略(Same-Origin Policy,SOP) 是 Web 安全的核心机制,用于:

  • 防止恶意网站读取另一个网站的敏感数据(如 Cookie、localStorage)
  • 防止 CSRF(跨站请求伪造)攻击
  • 保护用户隐私和数据安全

注意:跨域限制仅存在于浏览器,服务器之间的 HTTP 请求(如 Java HttpClient、Postman)不受此限制。

1.3 CORS(跨域资源共享)工作原理

CORS 是 W3C 标准,通过服务器设置 HTTP 响应头告知浏览器允许哪些源访问资源。

简单请求流程:

浏览器请求 → 服务器返回 Access-Control-Allow-Origin → 浏览器验证放行 

复杂请求(预检请求)流程:

浏览器 OPTIONS 预检 → 服务器返回允许方法/头 → 浏览器发送真实请求 → 返回数据 

二、完整的跨域处理方案列表

以下是适用于 Java 后端+Vue 前端的 6 种核心方案:

方案适用场景实现复杂度安全性需要后端配合
1. @CrossOrigin 注解少量接口快速测试⭐ 低中✅ 是
2. 全局 CORS 配置企业级标准方案⭐⭐ 中高✅ 是
3. 过滤器 Filter动态权限控制⭐⭐ 中高✅ 是
4. Spring Security 集成带权限系统的项目⭐⭐⭐ 高高✅ 是
5. Vue DevServer 代理开发环境专用⭐ 低
中
❌ 否
6. Nginx 反向代理生产环境部署⭐⭐ 中高❌ 否

三、方案详解

方案 1:@CrossOrigin 注解(最简单)

3.1.1 实现原理

通过在 Controller 或方法上添加 @CrossOrigin 注解,Spring MVC 会自动添加 CORS 响应头。

3.1.2 后端实现

单个接口跨域:

import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {
    // 允许指定域名的跨域请求
    @CrossOrigin(origins = "http://localhost:8080")
    @GetMapping("/api/demo")
    public String demo() {
        return "Hello from CORS!";
    }
}

多个接口跨域:

@RestController
@RequestMapping("/api")
// 类级别注解:该类下所有方法都支持跨域
@CrossOrigin(
    origins = {"http://localhost:8080", "http://localhost:3000"},
    methods = {RequestMethod.GET, RequestMethod.POST},
    maxAge = 3600
)
public class ApiController {
    @GetMapping("/users")
    public String getUsers() {
        return "Users data";
    }

    @PostMapping("/login")
    public String login() {
        return "Login success";
    }
}
3.1.3 前端配置(Vue + Axios)
// src/api/request.js
import axios from 'axios';

const request = axios.create({
    baseURL: 'http://localhost:8080', // 后端地址
    timeout: 5000
});

export default request;
<!-- src/components/Demo.vue -->
<template>
    <div>{{ message }}</div>
</template>
<script>
import request from '@/api/request';

export default {
    data() {
        return {
            message: ''
        };
    },
    async mounted() {
        try {
            const res = await request.get('/api/demo');
            this.message = res.data;
        } catch (error) {
            console.error('跨域请求失败:', error);
        }
    }
};
</script>
3.1.4 优缺点分析

优点:

  • 配置简单,一行注解搞定
  • 适合少量接口或快速原型开发

缺点:

  • 每个接口都需要单独配置,维护成本高
  • 不适合大规模企业项目
  • 无法统一管理跨域规则

方案 2:全局 CORS 配置(推荐)

3.2.1 实现原理

实现 WebMvcConfigurer 接口,重写 addCorsMappings 方法,统一配置全局跨域规则。

3.2.2 后端实现
package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 全局 CORS 配置类
 * 推荐用于企业级项目,统一管理跨域规则
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                // 对所有路径生效
                .allowedOrigins(
                        // 允许的前端域名(生产环境需指定具体域名)
                        "http://localhost:8080",
                        "http://localhost:3000",
                        "https://www.example.com"
                )
                .allowedMethods(
                        // 允许的 HTTP 方法
                        "GET", "POST", "PUT", "DELETE", "OPTIONS"
                )
                .allowedHeaders("*")
                // 允许的请求头
                .exposedHeaders("X-Total-Count", "X-Page-Count")
                // 暴露的响应头
                .allowCredentials(true)
                // 允许携带 Cookie(需与 allowedOrigins 配合)
                .maxAge(3600); // 预检请求缓存时间(秒)
    }
}
3.2.3 前端配置

Axios 实例配置:

// src/utils/request.js
import axios from 'axios';

const service = axios.create({
    baseURL: 'http://localhost:8080/api', // 后端 API 地址
    timeout: 10000,
    withCredentials: true // 携带 Cookie(需后端 allowCredentials=true)
});

// 请求拦截器:添加 Token 等
service.interceptors.request.use(config => {
    const token = localStorage.getItem('token');
    if (token) {
        config.headers['Authorization'] = 'Bearer ' + token;
    }
    return config;
}, error => {
    return Promise.reject(error);
});

// 响应拦截器:统一处理错误
service.interceptors.response.use(response => response, error => {
    if (error.response) {
        switch (error.response.status) {
            case 401:
                console.error('未授权,请登录');
                break;
            case 403:
                console.error('拒绝访问');
                break;
            case 500:
                console.error('服务器错误');
                break;
        }
    }
    return Promise.reject(error);
});

export default service;

API 封装:

// src/api/user.js
import request from '@/utils/request';

export const getUserList = (params) => {
    return request({
        url: '/users',
        method: 'get',
        params
    });
};

export const createUser = (data) => {
    return request({
        url: '/users',
        method: 'post',
        data
    });
};
3.2.4 优缺点分析

优点:

  • 统一管理,便于维护
  • 一次配置,全局生效
  • 支持精细化的权限控制

缺点:

  • 配置相对复杂
  • 需要理解 CORS 相关配置项

方案 3:过滤器 Filter(灵活控制)

3.3.1 实现原理

通过自定义 Filter,在请求链中手动设置 CORS 响应头,可实现动态的跨域逻辑。

3.3.2 后端实现
package com.example.filter;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * CORS 过滤器
 * 适用于需要动态判断跨域权限的场景
 */
@Component
public class CorsFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String origin = request.getHeader("Origin");
        // 动态判断是否允许该源跨域(可根据数据库、Redis 等动态配置)
        if (isAllowedOrigin(origin)) {
            response.setHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
            response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Max-Age", "3600");
        }

        // 处理 OPTIONS 预检请求
        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return;
        }
        filterChain.doFilter(request, response);
    }

    /**
     * 判断源是否在白名单中(可改为从数据库查询)
     */
    private boolean isAllowedOrigin(String origin) {
        if (origin == null) {
            return false;
        }
        // 允许的源列表(实际项目中可从配置文件或数据库读取)
        String[] allowedOrigins = {"http://localhost:8080", "http://localhost:3000", "https://www.example.com"};
        for (String allowed : allowedOrigins) {
            if (allowed.equals(origin)) {
                return true;
            }
        }
        return false;
    }
}
3.3.3 前端配置

同方案 2,使用 Axios 配置即可。

3.3.4 优缺点分析

优点:

  • 灵活性最高,可实现动态跨域控制
  • 可根据请求参数、用户角色等动态判断是否允许跨域
  • 适用于多租户、SAAS 系统等复杂场景

缺点:

  • 实现相对复杂
  • 需要手动维护 CORS 响应头逻辑
  • 性能略低于 Spring 内置 CORS 支持

方案 4:Spring Security 集成(带权限系统)

3.4.1 实现原理

在 Spring Security 安全框架中集成 CORS,确保跨域请求在经过安全链时正确处理。

3.4.2 后端实现

依赖配置(pom.xml):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Security 配置类:

package com.example.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * Spring Security + CORS 配置
 * 关键:CORS 必须在 Security 之前处理
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                // 启用 CORS(关键步骤)
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                // 禁用 CSRF(前后端分离项目通常禁用)
                .csrf(csrf -> csrf.disable())
                // 配置权限规则
                .authorizeHttpRequests(auth -> auth
                        // 放行 OPTIONS 预检请求
                        .requestMatchers(org.springframework.http.HttpMethod.OPTIONS, "/**").permitAll()
                        // 公开接口
                        .requestMatchers("/api/public/**").permitAll()
                        // 需要认证的接口
                        .anyRequest().authenticated());
        return http.build();
    }

    /**
     * CORS 配置源
     * Security 会自动读取此配置
     */
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        // 允许的源(生产环境必须指定具体域名)
        configuration.setAllowedOrigins(Arrays.asList(
                "http://localhost:8080",
                "http://localhost:3000",
                "https://www.example.com"
        ));
        // 允许的方法
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"));
        // 允许的请求头
        configuration.setAllowedHeaders(Arrays.asList("*"));
        // 允许携带凭证
        configuration.setAllowCredentials(true);
        // 暴露的响应头
        configuration.setExposedHeaders(Arrays.asList("X-Total-Count", "Authorization"));
        // 预检缓存时间
        configuration.setMaxAge(3600L);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
3.4.3 前端配置

Axios 配置(带 Token 认证):

// src/utils/request.js
import axios from 'axios';
import { Message } from 'element-ui';

const service = axios.create({
    baseURL: 'http://localhost:8080',
    timeout: 10000,
    withCredentials: true // 携带 Cookie(如 SessionId)
});

// 请求拦截器
service.interceptors.request.use(config => {
    // 从 localStorage 获取 Token
    const token = localStorage.getItem('access_token');
    if (token) {
        config.headers['Authorization'] = 'Bearer ' + token;
    }
    return config;
}, error => {
    return Promise.reject(error);
});

// 响应拦截器
service.interceptors.response.use(response => {
    const res = response.data;
    // 根据业务状态码处理
    if (res.code !== 200) {
        Message.error(res.message || '请求失败');
        // 401 未授权,跳转登录页
        if (res.code === 401) {
            localStorage.removeItem('access_token');
            window.location.href = '/login';
        }
        return Promise.reject(new Error(res.message || 'Error'));
    } else {
        return res;
    }
}, error => {
    console.error('请求错误:', error);
    // 401 未授权
    if (error.response && error.response.status === 401) {
        Message.error('未授权,请重新登录');
        localStorage.removeItem('access_token');
        window.location.href = '/login';
    }
    return Promise.reject(error);
});

export default service;

登录示例:

// src/api/auth.js
import request from '@/utils/request';

export const login = (data) => {
    return request({
        url: '/api/auth/login',
        method: 'post',
        data
    });
};

export const getUserInfo = () => {
    return request({
        url: '/api/user/info',
        method: 'get'
    });
};
3.4.4 优缺点分析

优点:

  • 完美集成 Spring Security 安全体系
  • 支持 Token 认证、Session 认证等多种认证方式
  • 适用于需要权限控制的复杂业务系统

缺点:

  • 配置复杂度较高
  • 需要理解 Spring Security 的工作原理
  • 新手容易出错

方案 5:Vue DevServer 代理(开发环境)

3.5.1 实现原理

利用 Webpack DevServer 内置的 http-proxy-middleware,在开发服务器层面对请求进行转发,绕过浏览器的同源限制。

3.5.2 前端配置

vue.config.js 配置(Vue CLI 项目):

// vue.config.js
module.exports = {
    devServer: {
        port: 8080, // 前端开发服务器端口
        host: '0.0.0.0',
        open: true,
        proxy: {
            // 代理规则 1:/api 开头的请求
            '/api': {
                target: 'http://localhost:8080', // 后端真实地址
                changeOrigin: true, // 修改请求头中的 Origin 为目标地址
                ws: true, // 支持 WebSocket 代理
                pathRewrite: {
                    '^/api': '' // 去掉/api 前缀(如果后端接口没有/api)
                },
                // 可选:添加自定义请求头
                headers: {
                    'X-Dev-Proxy': 'true'
                }
            },
            // 代理规则 2:/upload 开头的请求
            '/upload': {
                target: 'http://localhost:9090',
                changeOrigin: true,
                pathRewrite: {
                    '^/upload': '/files'
                }
            }
        }
    }
};

vite.config.js 配置(Vite 项目):

// vite.config.js
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    plugins: [vue()],
    server: {
        port: 5173,
        proxy: {
            '/api': {
                target: 'http://localhost:8080',
                changeOrigin: true,
                rewrite: (path) => path.replace(/^\/api/, '')
            }
        }
    }
});
3.5.3 Axios 配置
// src/utils/request.js
import axios from 'axios';

const service = axios.create({
    // 开发环境使用相对路径(会被代理转发)
    // 生产环境需配置为真实的后端地址
    baseURL: process.env.NODE_ENV === 'development' ? '/api' : 'http://api.example.com',
    timeout: 10000
});

export default service;

环境变量配置(.env.development):

NODE_ENV=development VUE_APP_BASE_API=/api

环境变量配置(.env.production):

NODE_ENV=production VUE_APP_BASE_API=https://api.example.com
3.5.4 优缺点分析

优点:

  • 开发环境最简单、最快捷的方案
  • 无需后端配合,前端独立完成
  • 支持 WebSocket 代理

缺点:

  • 仅适用于开发环境,生产环境不可用
  • 生产部署时需要修改 baseURL 或使用其他方案
  • 调试时代理转发可能影响问题定位

方案 6:Nginx 反向代理(生产环境)

3.6.1 实现原理

通过 Nginx 作为反向代理服务器,前端请求 Nginx 同源地址,Nginx 转发到后端。对浏览器而言是同源请求,完美解决跨域问题。

3.6.2 Nginx 配置

基础配置(推荐):

server {
    listen 80;
    server_name www.example.com;

    # 前端静态资源
    location / {
        root /usr/share/nginx/html; # Vue 打包后的 dist 目录
        index index.html;
        try_files $uri $uri/ /index.html; # 解决 Vue 路由刷新 404
    }

    # 后端 API 代理
    location /api/ {
        # 转发到后端真实地址
        proxy_pass http://localhost:8080/;
        # 关键:传递原始 Host 和客户端 IP
        proxy_set_header Host $proxy_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

完整 CORS 配置(后端不配置 CORS 时使用):

server {
    listen 80;
    server_name api.example.com;

    location / {
        # 允许的源(生产环境指定具体域名)
        add_header 'Access-Control-Allow-Origin' 'https://www.example.com' always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;
        add_header 'Access-Control-Max-Age' '3600' always;

        # 处理 OPTIONS 预检请求
        if ($request_method = OPTIONS) {
            return 204;
        }

        # 反向代理到后端
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

动态允许源配置:

server {
    listen 80;
    server_name api.example.com;

    # 动态设置允许的源
    set $cors_origin "";
    if ($http_origin ~* ^(https?://(localhost|www\.example\.com)(:[0-9]+)?$)) {
        set $cors_origin $http_origin;
    }

    location / {
        # 使用变量设置允许的源
        add_header 'Access-Control-Allow-Origin' $cors_origin always;
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS' always;
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
        add_header 'Access-Control-Allow-Credentials' 'true' always;

        if ($request_method = OPTIONS) {
            return 204;
        }

        proxy_pass http://localhost:8080;
    }
}
3.6.3 前端配置

Axios 配置:

// src/utils/request.js
import axios from 'axios';

// 生产环境使用 Nginx 代理的地址(同域)
const service = axios.create({
    baseURL: process.env.NODE_ENV === 'production' ? '/api' // 生产环境:Nginx 代理地址(同域)
        : 'http://localhost:8080', // 开发环境:使用后端直连或开发代理
    timeout: 10000,
    withCredentials: true
});

export default service;
3.6.4 优缺点分析

优点:

  • 生产环境最推荐方案
  • 前后端同域,天然避免跨域问题
  • 支持负载均衡、缓存、HTTPS 等高级功能
  • 无需修改后端代码

缺点:

  • 需要额外的 Nginx 服务器
  • 配置相对复杂
  • 需要运维知识

四、最佳实践建议

4.1 开发环境

推荐方案:Vue DevServer 代理 + 后端 CORS 全局配置

理由:

  • 前端独立开发,不依赖后端配置
  • 快速迭代,方便调试
  • 为生产环境做好准备

示例配置:

// 开发环境:vue.config.js
module.exports = {
    devServer: {
        proxy: {
            '/api': {
                target: 'http://localhost:8080',
                changeOrigin: true,
                pathRewrite: {
                    '^/api': ''
                }
            }
        }
    }
};

4.2 生产环境

推荐方案:Nginx 反向代理 + 后端 CORS 全局配置(双重保障)

理由:

  • Nginx 作为流量入口,统一处理跨域
  • 后端 CORS 作为备用,应对直接访问后端的情况
  • 支持多环境部署(开发、测试、生产)

架构图:

浏览器 ↓ Nginx (80/443)
├─ / → 前端静态资源 (同域)
└─ /api → 后端 API (同域代理)
↓ Spring Boot (8080)

4.3 复杂权限系统

推荐方案:Spring Security + CORS + Token 认证

关键配置:

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        .cors().and()
        .csrf().disable()
        .authorizeHttpRequests(auth -> auth
            .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .requestMatchers("/api/public/**").permitAll()
            .anyRequest().authenticated());
    return http.build();
}

前端 Token 管理:

// 请求拦截器:自动添加 Token
service.interceptors.request.use(config => {
    const token = localStorage.getItem('token');
    if (token) {
        config.headers['Authorization'] = 'Bearer ' + token;
    }
    return config;
});

4.4 多租户/SAAS 系统

推荐方案:过滤器 Filter + 动态跨域配置

实现思路:

  • 根据租户域名动态设置允许的源
  • 支持租户级别的跨域白名单管理
  • 从数据库或配置中心读取跨域规则
private boolean isAllowedOrigin(String origin, String tenantId) {
    // 从数据库查询该租户的跨域白名单
    List<String> allowedOrigins = tenantService.getCorsWhiteList(tenantId);
    return allowedOrigins.contains(origin);
}

五、常见问题排查

5.1 配置失败的典型原因

问题 1:No 'Access-Control-Allow-Origin' header is present

原因:

  • 后端未配置 CORS
  • Nginx 未添加跨域头
  • OPTIONS 预检请求失败

排查步骤:

  1. 打开浏览器开发者工具 → Network
  2. 查看请求的 Response Headers
  3. 检查是否有 Access-Control-Allow-Origin 字段
  4. 检查 OPTIONS 请求是否返回 204 或 200
问题 2:Credential is not supported for wildcard origin

原因:

  • 同时设置了 allowCredentials=true 和 allowedOrigins="*"
  • 浏览器不允许通配符源携带 Cookie

解决方案:

// 错误配置
config.setAllowCredentials(true);
config.setAllowedOrigins(Arrays.asList("*"));

// 正确配置
config.setAllowCredentials(true);
config.setAllowedOrigins(Arrays.asList("http://localhost:8080"));
问题 3:OPTIONS 预检请求返回 404/403

原因:

  • 后端未实现 OPTIONS 接口
  • Security 拦截了 OPTIONS 请求
  • Nginx 未处理预检请求

解决方案:

// Security 放行 OPTIONS
http.authorizeHttpRequests(auth -> auth
    .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll());
# Nginx 处理 OPTIONS
if ($request_method = OPTIONS) {
    return 204;
}

5.2 Nginx 配置踩坑

坑 1:proxy_pass 的斜杠问题
# 错误:路径会保留/api
location /api/ {
    proxy_pass http://localhost:8080; # 请求 /api/user → http://localhost:8080/api/user
}

# 正确:去掉/api 前缀
location /api/ {
    proxy_pass http://localhost:8080/; # 请求 /api/user → http://localhost:8080/user
}
坑 2:缺少 always 参数
# 错误:错误响应时不会添加跨域头
add_header 'Access-Control-Allow-Origin' 'http://localhost:8080';

# 正确:所有响应都添加跨域头
add_header 'Access-Control-Allow-Origin' 'http://localhost:8080' always;

5.3 Cookie 携带问题

现象:请求未携带 Cookie 或 Set-Cookie 不生效

原因:

  • 前端未设置 withCredentials: true
  • 后端未设置 allowCredentials: true
  • Cookie 的 SameSite 属性设置不当

解决方案:

前端:

axios.get('/api/user', { withCredentials: true });

后端:

config.setAllowCredentials(true);
config.setAllowedOrigins(Arrays.asList("http://localhost:8080")); // 不能是*

Cookie 设置:

Cookie cookie = new Cookie("token", tokenValue);
cookie.setHttpOnly(true);
cookie.setSecure(true); // HTTPS 必需
cookie.setPath("/"); // 如果需要跨域,设置 SameSite 为 None
cookie.setAttribute("SameSite", "None");
response.addCookie(cookie);

5.4 调试技巧

技巧 1:使用 curl 测试 CORS
# 测试 OPTIONS 预检
curl -X OPTIONS -H "Origin: http://localhost:8080" \
-H "Access-Control-Request-Method: GET" \
-v http://localhost:8080/api/user

# 查看响应头
curl -I http://localhost:8080/api/user
技巧 2:浏览器 Network 面板分析
  1. 打开开发者工具 → Network
  2. 勾选"Preserve log"
  3. 发送跨域请求
  4. 查看请求详情:
    • Request Headers:检查 Origin、Access-Control-Request-Method
    • Response Headers:检查 Access-Control-Allow-*
    • Console:查看具体错误信息
技巧 3:临时禁用浏览器安全策略(仅用于调试)
# Chrome 启动参数(仅开发调试使用,生产环境禁止)
chrome.exe --disable-web-security --user-data-dir="C:/temp/chrome-dev"

六、总结

6.1 方案对比表

方案适用场景推荐度生产可用性
@CrossOrigin 注解少量接口测试⭐⭐✅ 是
全局 CORS 配置企业级标准方案⭐⭐⭐⭐⭐✅ 是
过滤器 Filter动态权限控制⭐⭐⭐⭐✅ 是
Spring Security 集成带权限系统⭐⭐⭐⭐⭐✅ 是
Vue DevServer 代理开发环境⭐⭐⭐⭐⭐❌ 否
Nginx 反向代理生产环境⭐⭐⭐⭐⭐✅ 是

6.2 核心要点

  1. 跨域是浏览器的安全机制,服务器之间无此限制
  2. CORS 是最标准的解决方案,推荐后端配置
  3. 开发环境用代理,生产环境用 Nginx
  4. allowCredentials=true 时,allowedOrigins 不能是"*"
  5. Spring Security 需放行 OPTIONS 预检请求
  6. Nginx 配置注意斜杠和 always 参数
  7. 携带 Cookie 需前后端同时配置

6.3 推荐架构

标准企业级项目:

开发环境:Vue DevServer 代理 + 后端 CORS 全局配置
生产环境:Nginx 反向代理 + 后端 CORS 全局配置(双重保障)
权限系统:Spring Security + Token 认证

参考资料

  • Spring Framework CORS Documentation
  • MDN - CORS
  • Vue CLI DevServer Proxy
  • Nginx ngx_http_proxy_module

目录

  1. 前后端跨域处理全指南:Java 后端+Vue 前端完整解决方案
  2. 一、跨域基础概念
  3. 1.1 什么是跨域?
  4. 1.2 为什么会有跨域限制?
  5. 1.3 CORS(跨域资源共享)工作原理
  6. 二、完整的跨域处理方案列表
  7. 三、方案详解
  8. 方案 1:@CrossOrigin 注解(最简单)
  9. 3.1.1 实现原理
  10. 3.1.2 后端实现
  11. 3.1.3 前端配置(Vue + Axios)
  12. 3.1.4 优缺点分析
  13. 方案 2:全局 CORS 配置(推荐)
  14. 3.2.1 实现原理
  15. 3.2.2 后端实现
  16. 3.2.3 前端配置
  17. 3.2.4 优缺点分析
  18. 方案 3:过滤器 Filter(灵活控制)
  19. 3.3.1 实现原理
  20. 3.3.2 后端实现
  21. 3.3.3 前端配置
  22. 3.3.4 优缺点分析
  23. 方案 4:Spring Security 集成(带权限系统)
  24. 3.4.1 实现原理
  25. 3.4.2 后端实现
  26. 3.4.3 前端配置
  27. 3.4.4 优缺点分析
  28. 方案 5:Vue DevServer 代理(开发环境)
  29. 3.5.1 实现原理
  30. 3.5.2 前端配置
  31. 3.5.3 Axios 配置
  32. 3.5.4 优缺点分析
  33. 方案 6:Nginx 反向代理(生产环境)
  34. 3.6.1 实现原理
  35. 3.6.2 Nginx 配置
  36. 3.6.3 前端配置
  37. 3.6.4 优缺点分析
  38. 四、最佳实践建议
  39. 4.1 开发环境
  40. 4.2 生产环境
  41. 4.3 复杂权限系统
  42. 4.4 多租户/SAAS 系统
  43. 五、常见问题排查
  44. 5.1 配置失败的典型原因
  45. 问题 1:No 'Access-Control-Allow-Origin' header is present
  46. 问题 2:Credential is not supported for wildcard origin
  47. 问题 3:OPTIONS 预检请求返回 404/403
  48. Nginx 处理 OPTIONS
  49. 5.2 Nginx 配置踩坑
  50. 坑 1:proxy_pass 的斜杠问题
  51. 错误:路径会保留/api
  52. 正确:去掉/api 前缀
  53. 坑 2:缺少 always 参数
  54. 错误:错误响应时不会添加跨域头
  55. 正确:所有响应都添加跨域头
  56. 5.3 Cookie 携带问题
  57. 5.4 调试技巧
  58. 技巧 1:使用 curl 测试 CORS
  59. 测试 OPTIONS 预检
  60. 查看响应头
  61. 技巧 2:浏览器 Network 面板分析
  62. 技巧 3:临时禁用浏览器安全策略(仅用于调试)
  63. Chrome 启动参数(仅开发调试使用,生产环境禁止)
  64. 六、总结
  65. 6.1 方案对比表
  66. 6.2 核心要点
  67. 6.3 推荐架构
  68. 参考资料
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Android Studio 结合 Trae 使用 Kotlin 开发 WebView 应用
  • 线性表、顺序表与链表详解(C 语言实现)
  • 前端国际化实战:i18n 选型、架构设计与 RTL 布局避坑
  • 前端开发常被低估?聊聊工程化背后的隐形门槛
  • GPT-4o 多模态交互与端侧应用玩法解析
  • ERNIE-4.5-0.3B 轻量模型部署与实战测评
  • LightGlue ONNX C++ 推理实践
  • 免费 AI API 公益站上线,支持 GPT-4o 等模型
  • MacOS 极简安装 OpenClaw 之 Docker 版
  • Python 函数核心指南:参数传递、返回值与模块使用
  • GitHub Copilot Pro 学生认证与配置指南
  • 前端监控最佳实践与 Sentry 集成
  • OpenClaw 与 ToClaw 横评:AI 代理网关的产品化选型
  • 前端 TypeScript 高级技巧:提升代码安全性
  • Python 在 CentOS 系统上的安装与配置深度指南
  • 前端 DOM 操作核心知识与实战解析
  • 动态规划专题:子序列问题深度解析
  • Linux 下 libwebkit2gtk-4.1-0 安装实战:从零部署 GTK Web 渲染引擎
  • Java 模拟算法实战:LeetCode 经典题型解析
  • IDEA 中 AI 编程插件实测:Copilot、TRAE 与灵码深度对比

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online