首页 > Technology > 正文

前端 CORS 跨域报错怎么解决

fenij 2026-08-18 52 Technology

前端调用后端接口时,浏览器控制台最常见的报错之一就是 CORS。报错信息通常是 Access to fetch at '...' from origin '...' has been blocked by CORS policy。很多人第一反应是后端没开跨域,但实际情况里,简单请求和预检请求的处理方式并不一样,盲目配 * 有时候反而更糟。

快速判断属于哪种 CORS 报错

类型 触发条件 浏览器表现
简单请求 GET/POST/HEAD + 标准请求头 直接请求,后端响应头决定是否放行
预检请求 PUT/DELETE 或自定义头 先发起 OPTIONS,失败则阻断
带凭证请求 withCredentials: truecredentials: 'include' 不能用 Access-Control-Allow-Origin: *

后端放行方案

核心就三个响应头:

Access-Control-Allow-Origin: https://your-frontend.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization

Nginx 配置示例

location /api/ {
    add_header 'Access-Control-Allow-Origin' 'https://your-frontend.com' always;
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
    add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization' always;

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

Node.js / Express 配置示例

const cors = require('cors');
app.use(cors({
  origin: 'https://your-frontend.com',
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
}));
🌐
Allow-Origin
允许来源
🔧
Allow-Methods
允许方法
📋
Allow-Headers
允许请求头

前端规避方案

真正部署到生产环境时,跨域应该由后端处理。但本地开发阶段可以用这些方式临时解决:

  • Vite 代理: 配置 server.proxy,把前端 /api 转发到后端;
  • webpack devServer proxy: 原理相同,开发环境走同源;
  • 关闭浏览器安全策略: 只用于本地临时调试,不要作为常规方案。
// vite.config.js
export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true
      }
    }
  }
}

踩坑实录

有一次给管理后台做登录接口,前端用 credentials: 'include' 发送 Cookie。我在 Nginx 里图省事直接写了:

add_header 'Access-Control-Allow-Origin' '*' always;

结果预检请求一直失败,控制台报错说 The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'

问题很直接:带凭证时不能用 *。改成显式域名并加上 Access-Control-Allow-Credentials: true 才通过:

add_header 'Access-Control-Allow-Origin' 'https://admin.example.com' always;
add_header 'Access-Control-Allow-Credentials' 'true' always;

这个坑说明:看报错要看到最后一行,浏览器已经告诉你原因了。

常见问题

Q:配置了响应头还是报 CORS?
A:检查响应头是否真的到达了浏览器。很多反向代理或 CDN 会吞掉自定义头;也可能是 OPTIONS 预检请求没有返回对应头。

Q:多个前端域名怎么配 Allow-Origin?
A:后端根据请求头里的 Origin 做白名单判断,动态返回对应域名。静态写死只适合单域名。

Q:后端用 Spring Boot 怎么配?
A:用 @CrossOrigin 注解或全局 CorsRegistry,注意 allowCredentials = "true" 时同样不能用 *

关于 CORS 你还有什么没搞明白的场景?欢迎在 fenij.com 留言,一起把跨域问题彻底理清楚。

排错自查清单

  • ☐ 快速判断属于哪种 CORS 报错
  • ☐ 后端放行方案:核心就三个响应头:
  • ☐ 前端规避方案:真正部署到生产环境时,跨域应该由后端处理。但本地开发阶段可以用这些方式临时解决:
  • ☐ 踩坑实录:有一次给管理后台做登录接口,前端用 credentials: 'include' 发送 Cookie。我在 N
  • ☐ 常见问题:Q:配置了响应头还是报 CORS?A:检查响应头是否真的到达了浏览器。很多反向代理或 CDN 会吞掉自定义头;

关键命令速查

  • Access-Control-Allow-Origin: https://your-frontend.com Access-Control-Allow-Methods: GET,
  • location /api/ { add_header 'Access-Control-Allow-Origin' 'https://your-frontend.com' alwa
  • const cors = require('cors'); app.use(cors({ origin: 'https://your-frontend.com', methods:
  • // vite.config.js export default { server: { proxy: { '/api': { target: 'http://localhost:
  • add_header 'Access-Control-Allow-Origin' '*' always;
  • add_header 'Access-Control-Allow-Origin' 'https://admin.example.com' always; add_header 'A

相关延伸

更系统的排查思路,见 Technology 分类归档

补充:调 CORS 最常被坑的是「用了通配符 * 又带凭证」——浏览器会直接拒绝。开发期用 devServer 代理绕开,上线再按域名精确配置;只要请求带 cookie 或 Authorization,origin 就必须写死,不能偷懒用 *。预检请求(OPTIONS)返回 204 才算正常,很多 403 其实是预检没放行。带凭证的请求还要注意响应头带 Vary: Origin,否则 CDN 可能把错误结果缓存下发;本地验证用 curl -I 看 preflight 状态最直观。

相关完整手册

系统化的排查与配置思路,建议顺手收藏这几篇完整手册: