【跨域options】为什么你的跨域 POST 请求被浏览器“吞”了?

引言

在做跨域请求时,你是否遇到过这种怪事:在 Network 面板里,OPTIONS 预检请求返回了 200 OK,看起来一切正常;但紧随其后的 POST 请求却直接报了 CORS error,甚至点开详情还提示 "Provisional headers are shown"

这到底是浏览器的锅,还是后端的错?今晚我们就来扒开这层皮。


一、 罪魁祸首:被遗忘的"入场券"

在跨域场景下,浏览器会发起 OPTIONS 预检。如果你在请求中使用了非简单的 Header(如 JSON 的 Content-Type 或链路追踪的 traceparent),浏览器会发起"礼貌询问":

  • 浏览器问: Access-Control-Request-Headers: content-type, traceparent
  • 服务器答: Access-Control-Allow-Headers: Content-Type, Access-Token, ...

坑点就在这里: 如果服务器的白名单里漏掉了哪怕一个 Header(比如本文案例中的 traceparent),浏览器就会认为这场"商业洽谈"失败了。


二、 为什么 OPTIONS 是绿的,POST 却是红的?

这是最让人困惑的地方。既然"洽谈"失败,为什么 OPTIONS 不直接报错?

  1. OPTIONS 是"获取规则": 服务器成功处理了你的咨询请求,并如实告知了它的配置。从 HTTP 协议看,咨询过程是完美的,所以返回 200 OK
  2. POST 是"执行意图": 浏览器拿到服务器的规则后,发现和你手里的"会员卡"(traceparent)不匹配。为了安全,浏览器单方面拦截了 POST 请求,不让它真正发往服务器。
  3. "红色"是浏览器的警告: 那个红色的 POST 记录其实是浏览器生成的"虚拟记录",目的是告诉你: "你原本想发这个,但我把它按下了。" > 核心结论: OPTIONS 的成功代表"问答过程成功",不代表"准入结果成功"。

三、 关于 Origin 的安全防线

在排查过程中,我们曾想过:能不能手动在 Headers 里改 Origin

  • 答案是:不行。 在浏览器环境下,OriginForbidden Header,由浏览器强制控制。
  • 为什么? 如果开发者能改 Origin,那么钓鱼网站就能轻易伪装成银行官网,CORS 安全机制将形同虚设。
  • 真相: Origin 的存在不由后端决定,但它的"生死存亡"由后端决定。后端通过校验这个自动带上的 Origin 来决定是否给浏览器发放"过路费"(即 Access-Control-Allow-Origin 响应头)。

四、 避坑指南:如何彻底解决?

1. 后端侧(根治方案)

不要只配置 Origin。如果前端有自定义 Header(如分布式追踪、身份令牌),必须在 Access-Control-Allow-Headers 中显式添加。

  • 代码示例(Node.js):

    JavaScript

    arduino 复制代码
    res.header("Access-Control-Allow-Headers", "Content-Type, traceparent, Your-Custom-Header");

2. 前端侧(调试技巧)

当你看到 "Provisional headers are shown" 且伴随 CORS error 时:

  • 第一步: 检查 OPTIONS 请求头里的 Access-Control-Request-Headers
  • 第二步: 检查 OPTIONS 响应头里的 Access-Control-Allow-Headers
  • 第三步: 找茬,看谁多了,看谁少了。

结语

Web 开发中,CORS 不是敌人,而是保护数据的保镖。当你理解了浏览器、服务器和安全策略之间的那场"礼貌洽谈",这些诡异的红色报错就不再是迷雾。

相关推荐
葫芦和十三7 小时前
图解 MongoDB 05|文档模型设计:内嵌 vs 引用,反范式不是免费午餐
后端·mongodb·agent
LinXunFeng8 小时前
Obsidian - 使用 Share Note 分享笔记并自部署
前端·笔记·github
不能放弃治疗10 小时前
单 Agent 实现模式
后端
乘风gg12 小时前
为什么AI 时代来临,大部分人吃不到红利
前端·ai编程·claude
恋猫de小郭12 小时前
Android 限制侧载新进展,谷歌联合国内厂商推验证计划
android·前端·flutter
IT_陈寒12 小时前
Redis内存爆了,原来我漏掉了这个致命配置
前端·人工智能·后端
恋猫de小郭12 小时前
解读 Android 17 全新内存限制,有没有“豁免”后门?
android·前端·flutter
fliter13 小时前
最后一块拼图:用 bitvec 构造 IPv4 包,真正做出自己的 Ping
后端
Hyyy13 小时前
理解LLM的基本工作原理:预训练、微调、推理的区别
前端
fliter14 小时前
用 Rust 解析并生成 ICMP 包:checksum、nom 与 cookie-factory
后端