无需登录 数据私有 本地保存

CORS问题演示器 - 跨域错误说明

24
0
0
0

CORS 问题演示器 - 跨域错误说明

深入理解跨域资源共享(CORS)机制,通过真实请求演示成功与失败的跨域场景,掌握常见错误及解决方案。

预设演示场景

点击下方场景发起真实跨域请求,观察结果差异:

自定义URL测试

输入任意URL,测试其CORS配置:

请求结果
等待发起请求...点击左侧场景按钮或输入URL开始测试
───────────────────────────────
提示:打开浏览器开发者工具 → Network 面板
可观察完整的请求详情和预检请求(OPTIONS)
关键 CORS 响应头参考
响应头 作用 示例值
Access-Control-Allow-Origin 指定允许跨域访问的源(origin) *https://example.com
Access-Control-Allow-Methods 允许的HTTP方法(预检响应中使用) GET, POST, PUT, DELETE
Access-Control-Allow-Headers 允许的请求头(预检响应中使用) Content-Type, Authorization
Access-Control-Max-Age 预检请求缓存时间(秒) 86400(24小时)
Access-Control-Allow-Credentials 是否允许携带Cookie等凭证 true
Access-Control-Expose-Headers 允许客户端读取的响应头 X-Custom-Header, X-Rate-Limit
简单请求流程(Simple Request)

满足以下全部条件时,浏览器直接发送请求,无需预检:

✅ 方法为 GET / HEAD / POST
✅ Content-Type 为 text/plainmultipart/form-dataapplication/x-www-form-urlencoded
✅ 仅使用简单请求头(如 Accept、Accept-Language、Content-Language)
✅ 未设置自定义请求头
1
浏览器发送请求
携带 Origin 请求头,标明来源
2
服务器返回响应
响应中包含 Access-Control-Allow-Origin 头
3
浏览器校验
检查响应头是否允许当前源,通过则放行
预检请求流程(Preflight Request)

不满足简单请求条件时,浏览器先发送 OPTIONS 预检请求:

🔍 使用了 PUT / DELETE / PATCH 方法
🔍 Content-Type 为 application/json
🔍 携带了自定义请求头(如 Authorization、X-API-Key)
1
浏览器发送 OPTIONS 预检请求
询问服务器是否允许该跨域请求
2
服务器返回预检响应
包含 Allow-Methods、Allow-Headers 等头
3
预检通过,发送实际请求
浏览器确认权限后发送真正的请求
提示:打开浏览器 DevTools → Network,筛选 OPTIONS 请求,即可观察到预检请求。
常见 CORS 错误及解决方案
❌ 缺少 Allow-Origin

响应未包含 Access-Control-Allow-Origin 头。需要在服务端添加该响应头。

❌ 预检请求失败

OPTIONS 请求返回非 2xx 状态码,或缺少必要响应头。检查服务端是否正确处理 OPTIONS 请求。

⚠️ 凭证模式问题

携带 Cookie 时,Allow-Origin 不能为 *,必须指定具体源,且需设置 Allow-Credentials: true

⚠️ 自定义头未允许

自定义请求头未被 Access-Control-Allow-Headers 包含,需在服务端添加相应配置。

常见问题 FAQ
什么是 CORS?为什么浏览器要限制跨域请求?

CORS(Cross-Origin Resource Sharing,跨域资源共享)是一种浏览器安全机制。浏览器遵循同源策略(Same-Origin Policy),默认禁止网页向不同源(协议、域名、端口任一不同)的服务器发送请求并读取响应。

这是为了防止恶意网站窃取用户在其他网站的数据(如银行信息、邮件等)。CORS 通过特定的 HTTP 响应头,让服务器明确声明允许哪些外部源访问其资源,从而在安全与灵活性之间取得平衡。

关键理解:CORS 限制的是浏览器读取响应,而非请求本身。后端服务器之间的通信不受 CORS 限制。

CORS 错误发生在前端还是后端?如何排查?

CORS 错误发生在浏览器端——浏览器检测到跨域响应的响应头不满足要求,于是拦截响应并抛出错误。排查步骤:

  1. 打开浏览器 DevTools → Console,查看具体错误信息。
  2. 切换到 Network 面板,找到失败的请求,查看响应头。
  3. 检查响应中是否包含 Access-Control-Allow-Origin 头。
  4. 如果是预检失败,筛选 OPTIONS 请求,检查预检响应。
  5. 确认服务端 CORS 配置是否正确(允许的源、方法、头)。

常见错误信息:"Access to fetch at '...' from origin '...' has been blocked by CORS policy"

如何在服务端配置 CORS?不同后端框架怎么做?

通用原则:在响应中添加 Access-Control-Allow-Origin 等相关头即可。以下是常见框架的配置方式:

  • Express.js (Node.js):使用 cors 中间件,app.use(cors({ origin: 'https://example.com' }))
  • Flask (Python):使用 flask-cors 扩展,CORS(app, origins=['https://example.com'])
  • Spring Boot (Java):使用 @CrossOrigin 注解或全局配置 WebMvcConfigurer
  • Nginx:在配置中添加 add_header Access-Control-Allow-Origin *;
  • Django:使用 django-cors-headers

生产环境建议明确指定允许的源,而非使用通配符 *

JSONP 和 CORS 有什么区别?现在还推荐用 JSONP 吗?

JSONP(JSON with Padding)是 CORS 出现之前的跨域解决方案。它利用 <script> 标签不受同源策略限制的特性,通过动态创建 script 标签来获取数据。

对比维度CORSJSONP
支持方法所有HTTP方法仅 GET
安全性较高,精细控制较低,易受XSS攻击
错误处理完善难以处理错误
推荐程度✅ 现代标准❌ 已过时,不推荐

除非需要兼容非常老旧的浏览器,否则应使用 CORS

为什么 Postman / curl 可以正常请求,浏览器却报 CORS 错误?

这是一个非常常见的困惑。Postman、curl 等工具不受 CORS 限制,因为它们不是浏览器环境。

CORS 是浏览器内置的安全策略,由浏览器强制执行。Postman 是原生应用程序,它直接发送 HTTP 请求并接收响应,不会检查 Access-Control-Allow-Origin 头。

同理,后端服务之间的相互调用也不受 CORS 限制。CORS 只影响浏览器中的 JavaScript 发起的跨域请求。

Access-Control-Allow-Origin 设为 * 有什么安全隐患?

使用通配符 * 意味着允许任意网站跨域访问该资源。潜在风险包括:

  • 数据泄露:任何网站都可以通过 JavaScript 读取该接口的响应数据。
  • CSRF 攻击面扩大:攻击者可以更容易地构造跨站请求。
  • 无法使用凭证模式:Allow-Origin* 时,浏览器不允许携带 Cookie(credentials: 'include' 会报错)。

对于公开的、不涉及用户隐私的 API(如公共数据集),使用 * 是可接受的。对于涉及用户数据的 API,必须指定具体的允许源

什么是"简单请求"?预检请求(Preflight)何时触发?

简单请求必须同时满足以下条件:

  1. 方法为 GET、HEAD 或 POST
  2. 仅使用浏览器自动设置的请求头和少数简单头(Accept、Accept-Language、Content-Language、Content-Type)
  3. Content-Type 仅限于 application/x-www-form-urlencodedmultipart/form-datatext/plain
  4. 未使用 ReadableStream

只要不满足以上任一条件,浏览器就会先发送 OPTIONS 预检请求,向服务器确认是否允许该跨域请求。

常见的触发预检场景:使用 Content-Type: application/json、携带 Authorization 头、使用 PUT/DELETE 方法。

开发阶段如何快速解决 CORS 问题?

开发阶段的几种快速方案:

  • 浏览器插件:使用 "CORS Unblock" 等浏览器扩展(仅限开发测试,不影响他人)。
  • 本地代理:使用 Vite/Webpack 的 devServer proxy 功能,将 API 请求代理到目标服务器。
  • 启动浏览器时禁用安全策略:chrome --disable-web-security --user-data-dir=/tmp(仅限本地测试,非常危险)。
  • 后端临时配置:在开发环境添加宽松的 CORS 头。

⚠️ 警告:切勿在生产环境使用上述不安全的做法!