Skip to content

跨域是什么,CORS 怎么工作? ​

浏览器的同源策略规定:协议、主机、端口有一个不同,脚本就不能随意读另一个源的响应。CORS 是服务器用响应头明确允许某个源来读。它限制的是「脚本能不能读」,不是「请求能不能发出去」。

原理 ​

简单请求会直接发出,例如 GET、POST、HEAD,且自定义头很少,Content-Type 属于 text/plain、application/x-www-form-urlencoded、multipart/form-data 之一。响应里要有 Access-Control-Allow-Origin,其值是具体源或 *。对不上的话,脚本拿不到响应,浏览器控制台会报 CORS 错误。

不满足简单请求条件时,浏览器先发 OPTIONS 预检,询问是否允许这个方法、这些头。服务器用下面几个头回答:

  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers
  • Access-Control-Max-Age:预检结果可以缓存多久

要带 Cookie 时,前端把 fetch 的 credentials 设为 include,服务器返回 Access-Control-Allow-Credentials: true,并且 Allow-Origin 必须是具体源,不能是 *。

开发环境常用开发服务器把接口代理到同主机,浏览器看到的是同源,从而绕开这套检查。生产环境要在真正的接口上配置 CORS,或者由自己的服务端转发。

JSONP 利用的是 script 标签不受这套读取限制,只能发 GET,而且等于在页面里执行别人的脚本。现在不要用它做接口方案。

追问 ​

为什么 Postman 没有跨域问题?

同源策略是浏览器给网页脚本加的。Postman、服务端和 curl 不走这套检查。

CORS 能代替 CSRF 防护吗?

不能。跨站表单照样能把请求发出去。见 CSRF。

易错点 ​

  • 端口不同也是跨源,localhost:5173 和 localhost:3000 不同源。
  • 预检失败时,业务请求不会发出,抓包里往往只有 OPTIONS。
  • Allow-Origin: * 和携带凭证不能同时使用。

相关 ​