🏠 首页 攻略 CORS是什么?浏览器拦截跨域请求的元凶

CORS是什么?浏览器拦截跨域请求的元凶

一篇文章搞懂CORS跨域问题,包括原理、报错信息和解决方案

一句话定位

CORS(跨域资源共享)是浏览器用来保护用户安全的一套机制,它阻止网页去请求其他域的资源,除非服务器明确说"我允许"。


是什么?

打个比方:你家住在小区A,你家门口有个保安(这就是浏览器的同源策略)。保安规定,你只能自己小区的住户互相串门。

现在你想到小区B的朋友家做客。你跑到小区B门口,朋友也在家、也欢迎你,但小区B门口的保安不认你,因为你的身份证(域名)不是这个小区的。

CORS就是小区B保安手里的那本"访客白名单"。如果小区B的保安在白名单里看到了你家小区的名字,他就会放行。如果没有,他就会把你的访问请求拦下来。

在技术上,“域"包括三个部分必须完全一样才算同源:

  • 协议(http还是https)
  • 域名(example.com还是api.example.com)
  • 端口(80还是8080)

只要这三个里有一个不一样,浏览器就认为这是跨域请求,CORS就会介入。


有什么用?

CORS的核心作用是安全。如果没有CORS,想象一下这个场景:

你在银行网站登录了账户,然后随手访问了一个恶意网站。这个恶意网站可以通过JavaScript悄悄向银行发起请求,读取你的余额、转走你的钱。浏览器不会有任何拦截。

CORS就是来堵这个漏洞的。它确保:只有你信任的网站,才能通过JavaScript读取你的数据。

对开发者来说,理解CORS也很重要。很多后端接口明明没问题,但前端调用时就报错。90%的情况都是CORS在拦着。


常见报错

你在浏览器控制台经常能看到这样的错误:

Access to fetch at ‘https://api.example.com/data' from origin ‘https://mysite.com’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

翻译成人话就是:

你的前端网站(mysite.com)想去请求api.example.com的数据,但api.example.com返回的响应里没有"允许跨域"的标记,所以浏览器把请求拦掉了。

还有一种情况叫预检请求失败。有些请求比较"隆重”(比如用了自定义Header、POST携带JSON),浏览器会先发一个OPTIONS请求探路。如果服务器不回应或者不通过,正式请求也不会发出。


怎么解决?

解决CORS问题,关键在服务器端,不在前端。

后端配置响应头

服务器需要在HTTP响应里加一些头信息,告诉浏览器"我允许哪些域名来请求我"。最常见的配置:

Access-Control-Allow-Origin: https://mysite.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization

Access-Control-Allow-Origin可以设成具体的域名,也可以设成*(允许所有域名,但不推荐,尤其有用户数据的时候)。

常见场景

Node.js + Express

const cors = require('cors');
app.use(cors({ origin: 'https://mysite.com' }));

Python + Flask

from flask_cors import CORS
CORS(app, origins=["https://mysite.com"])

Nginx反向代理

add_header Access-Control-Allow-Origin "https://mysite.com";

开发环境偷懒法:很多前端开发框架支持配置代理,把跨域请求变成同源请求。比如Vite里配个proxy,或者在package.json里设"proxy"。这只适合开发阶段,生产环境还是要走正规CORS配置。


几个常见误区

误区一:CORS是后端的安全机制。 错。CORS是浏览器的行为,后端不设CORS头,用curl或Postman照样能请求到数据。后端自己的权限控制(比如token验证)才是真正管安全的。

误区二:把Access-Control-Allow-Origin设成星号就万事大吉。 不行。如果请求带Cookie或Authorization头,浏览器会拒绝星号通配。这时候必须写明具体域名。

误区三:跨域就是不能访问。 不是的。图片、脚本、样式标签的src属性,天然就是跨域的,浏览器一直允许。CORS拦的只是JavaScript发起的请求(fetch、XMLHttpRequest)。


总结

CORS不是bug,它是浏览器给网站穿的安全铠甲。

理解它的工作原理,你就能在开发中快速定位跨域问题——99%的情况只需要在后端加对几个响应头就行。

下次再看到"CORS error"别慌了,看看是不是服务器没把白名单写对。