跨域

#CORS #HTTP #请求头

跨域与 CORS

1) 什么是跨域

浏览器判断“是否同源/是否跨域(跨源)”只看 协议 + 域名 + 端口(scheme/host/port)。三者任意一个不同,就是跨域。

  • http://localhost:8001http://localhost:8002:跨域(端口不同)
  • http://a.comhttps://a.com:跨域(协议不同)
  • http://a.comhttp://b.com:跨域(域名不同)

注意:path 不参与跨域判断
(同源/CORS 概览)https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS


2) 请求头是什么

HTTP 请求由「请求行 + 请求头(headers) + 空行 + 可选正文(body)」组成。

  • 请求头:一堆 Key: Value,描述这次请求的“元信息/上下文”,比如:
    • Host:要访问哪个站点(虚拟主机选择相关)
    • Origin:浏览器自动带的“发起请求的源”(跨域时关键)
    • Accept:期望响应的数据类型
    • Content-Type请求 body 的格式(POST/PUT 等常见)
    • Authorization:认证信息(常触发预检)

3) CORS 把跨域请求分为两类

核心区别:是否需要 preflight(预检 OPTIONS)

A. 简单请求(simple request)

跨域情况下满足条件 → 浏览器 直接发送真正请求,不先发 OPTIONS。

简单请求需要同时满足:

  1. 方法是:GET / HEAD / POST
  2. 你在代码里手动设置的请求头属于“安全白名单”(不展开死背,记住:Authorization、自定义 X-* 往往会让它变非简单)
  3. 若是 POSTContent-Type 只能是以下三种之一:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

(Simple requests 条件)https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests

简单请求的流程

  1. 浏览器发送真正请求(带 Origin)到跨域服务器
  2. 服务器返回响应
  3. 浏览器检查响应里是否允许该源读取结果:
    • Access-Control-Allow-Origin
    • 若允许 → JS 能读到响应
    • 若不允许/缺失 → 请求可能已到后端,但浏览器不让 JS 读取响应(控制台报 CORS)

重要纠错Access-Control-Allow-Origin 的值只能是:


B. 非简单请求(preflighted request)

只要不满足简单请求条件(常见原因:Content-Type: application/json、带 Authorization、方法是 PUT/DELETE 等),浏览器通常会:

先发预检 OPTIONS(preflight),问服务器“我等会儿这样请求行不行?”

预检请求大概长这样:

OPTIONS /api HTTP/1.1
Origin: http://localhost:8001
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization, content-type

服务器如果同意,需要在 OPTIONS 的响应 里声明允许,例如:

Access-Control-Allow-Origin: http://localhost:8001
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Authorization, Content-Type

通过预检后,浏览器才会发真正请求;预检不通过,真正请求通常不会发出。


Reference

Cross-Origin Resource Sharing (CORS)| MDN Preflight 机制| MDN HTTP 报文结构
Content-Type