CORS错误 - 跨域资源共享问题详解

CORS(Cross-Origin Resource Sharing,跨域资源共享)是前端开发中常见的跨域访问问题。本文详细介绍 CORS 的原理、错误原因及解决方案。

什么是 CORS

CORS 是浏览器的安全机制,用于限制网页从不同源(域名、协议、端口)发起请求。浏览器会先发送预检请求(OPTIONS),确认服务器允许后才发送实际请求。

术语 说明 示例
同源 协议、域名、端口完全相同 http://example.com/page 和 http://example.com/api
跨域 任一要素不同 http://example.com 和 http://api.example.com
Origin 请求来源标识 http://localhost:8080

常见 CORS 错误信息

错误信息 含义
Access to fetch at 'http://...' from origin 'http://...' has been blocked by CORS policy 跨域请求被阻止
No 'Access-Control-Allow-Origin' header is present on the requested resource 服务器未返回 CORS 头
Access-Control-Allow-Origin' must be http://... or * Origin 与允许的来源不匹配
Credentials not supported if the CORS header 'Access-Control-Allow-Credentials' is true 不允许发送认证信息

解决方案一:后端设置 CORS 响应头

在服务器响应中添加 CORS 相关的 HTTP 头:

Node.js/Express

// 安装 cors 中间件 npm install cors // 使用 const cors = require('cors'); app.use(cors()); // 允许所有来源 // 或指定来源 app.use(cors({ origin: 'http://localhost:3000', credentials: true }));

Python/Flask

from flask_cors import CORS app = Flask(__name__) CORS(app, resources={r"/api/*": {"origins": "*"}}) # 或指定来源 CORS(app, origins="http://localhost:3000", allow_headers="Content-Type", supports_credentials=True)

Nginx 配置

# 在 server 或 location 块中添加 add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; add_header Access-Control-Allow-Headers "Content-Type, Authorization"; add_header Access-Control-Allow-Credentials "true"; # 预检请求处理 if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin $http_origin; add_header Access-Control-Allow-Methods "GET, POST, OPTIONS"; add_header Access-Control-Max-Age "3600"; return 204; }

解决方案二:开发环境代理

使用开发服务器的代理功能,将请求转发到后端:

Vite 配置代理

// vite.config.js export default { server: { proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } } }

Webpack Dev Server 代理

// webpack.config.js module.exports = { devServer: { proxy: { '/api': { target: 'http://localhost:3000', changeOrigin: true, pathRewrite: { '^/api': '' } } } } };

解决方案三:JSONP(仅 GET 请求)

// 前端 function jsonp(url, callback) { const script = document.createElement('script'); const callbackName = 'jsonp_' + Date.now(); window[callbackName] = function(data) { callback(data); delete window[callbackName]; }; script.src = url + (url.includes('?') ? '&' : '?') + callback= + callbackName; document.head.appendChild(script); } jsonp('http://api.example.com/data', function(data) { console.log(data); });

解决方案四:开发阶段允许所有来源

仅限开发环境使用:

Chrome 启动参数

# Windows chrome.exe --disable-web-security --user-data-dir=C:\temp # Mac open -a Google\ Chrome --args --disable-web-security --user-data-dir=/tmp/chrome

VS Code 插件

安装 "Allow CORS: Access-Control-Allow-Origin" 插件

CORS 常见配置说明

响应头 说明 示例值
Access-Control-Allow-Origin 允许的来源 *http://localhost:3000
Access-Control-Allow-Methods 允许的 HTTP 方法 GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers 允许的请求头 Content-Type, Authorization
Access-Control-Allow-Credentials 是否允许发送 Cookie true(需配合具体 Origin)
Access-Control-Max-Age 预检结果缓存时间(秒) 86400(24小时)

生产环境最佳实践

实践 说明
指定具体 Origin 不使用 *,明确允许的域名
限制允许的方法 只开放实际需要的 HTTP 方法
设置合理的缓存时间 减少预检请求,提升性能
使用 HTTPS 安全传输,避免中间人攻击
← CSS无效 JS错误 →