聊一聊跨域错误CORS

遇到 CORS(跨域资源共享) 错误是前端开发中的"家常便饭"。当浏览器控制台出现类似 Access to XMLHttpRequest from origin 'xxx' has been blocked by CORS policy 的报错时,通常意味着浏览器出于安全考虑,拦截了你的请求。别担心,我为你整理了从"快速解决"到"深度排查"的完整方案。

🛠️ 1. 什么是跨域

在解决之前,请确认是否真的跨域。只要协议、域名、端口三者中任意一个不同,就是跨域。

场景 当前页面 URL 请求接口 URL 是否跨域 原因
1 http://localhost:3000 http://localhost:3000/api 端口、域名、协议完全一致
2 http://localhost:3000 https://localhost:3000/api 协议不同 (http vs https)
3 http://localhost:3000 http://localhost:8080/api 端口不同
4 http://localhost:3000 http://api.example.com 域名不同

🚀 2. 解决方案

根据你的开发环境(前端/后端),选择最适合的一种

💻 方案一:前端开发环境(使用代理 Proxy)

如果你使用的是 ViteWebpack (Vue/React),可以在本地开发服务器配置代理,让请求先发给本地服务器,再由服务器转发给后端。这样浏览器认为是同源请求,不会触发 CORS。

  • Vite 配置 (vite.config.js):

    javascript 复制代码
    export default {
      server: {
        proxy: {
          '/api': {
            target: 'http://localhost:8080', // 后端真实地址
            changeOrigin: true, // 修改请求头中的 origin,让后端以为是它自己发的
            rewrite: (path) => path.replace(/^\/api/, '')
          }
        }
      }
    }
🛡️ 方案二:后端配置 CORS 响应头

最标准解决方式就是后端需要在响应头中明确告诉浏览器:"我允许你这个域名来访问我"。

  • 通用响应头:

    bash 复制代码
    Access-Control-Allow-Origin: http://localhost:3000 
    # 或者 * (但带cookie时不能用*)
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
    Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
  • Spring Boot (Java) 示例:

    java 复制代码
    @Configuration
    public class CorsConfig {
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurer() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**")
                            .allowedOriginPatterns("*") // 允许的源
                            .allowedMethods("*")
                            .allowedHeaders("*")
                            .allowCredentials(true); // 允许携带cookie
                }
            };
        }
    }
🗂️ 方案三:Nginx 反向代理

将前端和后端都部署在同一个 Nginx 下,让 Nginx 去做请求转发。对外只有一个域名,从根本上消灭跨域。

配置示例

java 复制代码
server {
    listen 80;
    server_name yourdomain.com;

    # 前端静态资源
    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;
    }

    # 代理 API 请求到后端
    location /api/ {
        proxy_pass http://localhost:8080; 
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

🔍 3. 常见报错深度解析

如果你的请求涉及 PUT/DELETE 方法 或者携带了 自定义 Header (如 token),浏览器会先发送一个 OPTIONS 预检请求。常见报错

Response to preflight request doesn't pass access control check

排查步骤

  1. 检查 OPTIONS 请求: 打开浏览器 Network 面板,看 OPTIONS 请求是否返回了 200204
  2. 后端是否处理 OPTIONS: 确保后端路由能正确响应 OPTIONS 请求,并返回正确的 CORS 头(如 Access-Control-Allow-Methods)。
  3. Header 是否匹配: 前端请求头中如果有 X-Token,后端的 Access-Control-Allow-Headers 中必须包含 X-Token

如果你的请求需要携带 Cookie(withCredentials: true),有两点必须注意:

后端 Access-Control-Allow-Origin 不能为 *,必须指定域名(如 http://localhost:3000

前端需设置 credentials: 'include'(Fetch)或 withCredentials = true(XHR)

📌 总结建议

  • 本地开发: 使用 Vite/Webpack 的 Proxy 代理。
  • 联调/测试: 让后端同学开启 CORS 支持。
  • 生产上线: 使用 Nginx 反向代理,既安全又高效。
相关推荐
岁岁的O泡奶2 天前
[NSSCTF 2022 Spring Recruit]babyphp
经验分享·web·ctf
里欧跑得慢4 天前
AI 驱动的 UI 国际化方案自动适配:从单一语言到多语言布局的智能转换
前端·css·flutter·web
里欧跑得慢5 天前
Flutter 像素级还原:设计稿到代码的视觉无损转换技巧
前端·css·flutter·web
深念Y7 天前
# CC-Switch + Claude/Codex 折腾教训记录
运维·服务器·网络·ai·agent·web·ccsiwtch
钛态7 天前
Vite 中的 CSS 工程化:从 CSS Modules 到 UnoCSS 的渐进式迁移
前端·vue·react·web
QYRdata9 天前
18.3%年复合增长率!2026-2032年Web应用与API安全领域,增长态势领跑行业
安全·web
Sagittarius_A*9 天前
Burst Lab | PHP 审计 14|反序列化(四):字符串逃逸与绕过技巧
开发语言·安全·php·web·反序列化
慧都小项9 天前
夜间Web回归跑到一半停了?TestComplete 15.83提升批量测试稳定性
前端·测试工具·数据挖掘·回归·汽车·web
山甫aa11 天前
日志技术 Logback + Slf4j —— 从零开始的 Web 后端学习
java·后端·学习·web·logback
Sagittarius_A*12 天前
【好靶场】PHP反序列化入门练习
安全·php·web·反序列化