遇到 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)
如果你使用的是 Vite 或 Webpack (Vue/React),可以在本地开发服务器配置代理,让请求先发给本地服务器,再由服务器转发给后端。这样浏览器认为是同源请求,不会触发 CORS。
-
Vite 配置 (
vite.config.js):javascriptexport default { server: { proxy: { '/api': { target: 'http://localhost:8080', // 后端真实地址 changeOrigin: true, // 修改请求头中的 origin,让后端以为是它自己发的 rewrite: (path) => path.replace(/^\/api/, '') } } } }
🛡️ 方案二:后端配置 CORS 响应头
最标准解决方式就是后端需要在响应头中明确告诉浏览器:"我允许你这个域名来访问我"。
-
通用响应头:
bashAccess-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
排查步骤
- 检查 OPTIONS 请求: 打开浏览器 Network 面板,看
OPTIONS请求是否返回了200或204。 - 后端是否处理 OPTIONS: 确保后端路由能正确响应
OPTIONS请求,并返回正确的 CORS 头(如Access-Control-Allow-Methods)。 - Header 是否匹配: 前端请求头中如果有
X-Token,后端的Access-Control-Allow-Headers中必须包含X-Token。
⚠️ 特殊情况:携带 Cookie
如果你的请求需要携带 Cookie(withCredentials: true),有两点必须注意:
后端 Access-Control-Allow-Origin 不能为 *,必须指定域名(如 http://localhost:3000)
前端需设置 credentials: 'include'(Fetch)或 withCredentials = true(XHR)
📌 总结建议
- 本地开发: 使用 Vite/Webpack 的 Proxy 代理。
- 联调/测试: 让后端同学开启 CORS 支持。
- 生产上线: 使用 Nginx 反向代理,既安全又高效。