← 返回题目列表

CORS 预检请求是什么?什么时候会触发?

高频 中等 第 10 / 26 题 更新于 2026/07/28
前端网络CORS预检请求OPTIONS

简化版

CORS 预检请求是浏览器在复杂跨域请求前发送的 OPTIONS 请求,用来询问服务器是否允许真实请求。使用非简单方法、自定义请求头或特殊 Content-Type 时通常会触发预检。服务器允许后,浏览器才发送真实请求。

详细版

简单请求通常不会预检,需要满足:

  • 方法是 GET、HEAD、POST。
  • 请求头只包含安全列表内的头。
  • Content-Type 是 text/plainmultipart/form-dataapplication/x-www-form-urlencoded

触发预检的常见情况:

  • PUT、DELETE、PATCH。
  • 非 CORS 安全列表请求头,如 Authorization。
  • Content-Type 为 application/json

预检响应常见头:

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers
  • Access-Control-Max-Age

完整版教学

一、为什么需要预检

复杂请求可能对服务器产生副作用,例如 DELETE 删除资源,或者带自定义头表达特殊权限。

浏览器先发 OPTIONS 询问服务器是否允许,避免直接发送潜在危险请求。

这是浏览器和服务器之间的安全协商。

二、预检流程

浏览器发现请求是复杂请求后,会自动发送 OPTIONS。

请求里会带上真实请求的方法和头信息。服务器返回允许的方法和头后,浏览器才继续发送真实请求。

如果预检失败,真实请求不会由浏览器发出,前端会看到 CORS 错误。

三、预检缓存

Access-Control-Max-Age 可以缓存预检结果。在缓存时间内,相同跨域请求不必每次都预检。

这能减少 OPTIONS 请求数量,但不能设置得完全不受控。权限策略变化时,也要考虑缓存影响。

四、面试追问与工程落地

面试官可能问:“为什么加了 Authorization 后多了一个 OPTIONS?”

因为 Authorization 是自定义请求头,不属于简单请求安全列表,会触发 CORS 预检。浏览器要先确认服务端允许这个 header。

工程中如果 OPTIONS 被网关拦截或没有正确响应,真实接口即使正常也无法被浏览器调用。

五、浏览器到底发送了什么

预检请求会声明即将使用的方法和非 safelisted 请求头:

OPTIONS /orders HTTP/1.1
Origin: https://app.example
Access-Control-Request-Method: PATCH
Access-Control-Request-Headers: authorization, content-type

服务端不是返回 200 就够了,还要给出匹配授权:

Access-Control-Allow-Origin: https://app.example
Access-Control-Allow-Methods: PATCH
Access-Control-Allow-Headers: authorization, content-type
Access-Control-Max-Age: 600
变化是否常触发预检原因
POST + text/plain方法与媒体类型在 safelist
POST + application/jsonContent-Type 不在 safelist
GET + Authorization该请求头不在 safelist
DELETE方法不在 safelist

“简单请求”不等于安全请求,它只是历史上网页表单本就能发出的请求集合,因此浏览器不先预检。

六、性能、缓存和排障数字例子

若页面对同一跨源 API 每分钟发 60 次 PATCH,而预检不缓存,网络层会看到约 120 次请求。允许缓存 600 秒后,在浏览器认可且请求条件相同时,理想情况下 10 分钟内可从约 1200 次降到 601 次左右,但各浏览器有自己的缓存上限和分区策略。

预检缓存 key 会受来源、目标、方法和请求头集合影响。今天加一个 X-Trace-Id,就可能产生新的预检条件;不要为了省 OPTIONS 把 Allow-Headers 写成无法审计的宽泛集合。

排障时先单独请求 OPTIONS,检查网关是否把它重定向、鉴权拦截或返回 404;再比较请求声明与响应允许值。预检成功后真实请求仍可能因业务鉴权失败,这两层错误不能混成“都是 CORS”。

预检失败 → 浏览器不发送真实复杂请求
预检成功 → 发送真实请求 → 仍需身份、权限、业务校验

七、常见误区与追问

  • 误区:所有跨域请求都会先发 OPTIONS。 只有不满足 CORS safelist 的请求才需要预检。
  • 误区:OPTIONS 返回 200 就算预检成功。 允许来源、方法和请求头必须与请求匹配。
  • 误区:预检能替服务端阻止恶意客户端。 curl 等客户端可直接发真实请求,服务端仍需鉴权。
  • 追问:为什么 application/json 常触发预检? 它不属于 CORS safelisted Content-Type。
  • 追问:Authorization 是浏览器禁止的头吗? 不是,但它不在 safelist,跨源使用前通常要预检并获得允许。
  • 追问:Max-Age 越长越好吗? 不一定,策略收紧后旧授权可能在客户端缓存到期前继续生效。
  • 追问:为什么网关不应强制 OPTIONS 登录? 预检本身通常不携带业务凭证,它是在询问真实请求能否发送。

八、加强记忆

  1. 触发条件:方法、头或 Content-Type 超出 safelist。
  2. 两步流程:OPTIONS 协商成功后,浏览器才发真实复杂请求。
  3. 响应匹配:Origin、Method、Headers 三类授权缺一不可。
  4. 性能手段:适度 Max-Age,减少请求头变化和不必要跨源。
  5. 安全边界:预检不是鉴权,也不能约束非浏览器攻击者。
  6. 排障顺序:先查 OPTIONS 的网络响应,再查真实请求业务结果。