跳到正文
>_ITDITDWeb 安全平台

术语表

CORS 是什么 — 原理,以及配置错误(CORS misconfiguration)会引发什么

CORS(跨源资源共享)是浏览器用来控制「某个网站的 JavaScript 能否读取另一个源的 API 响应」的机制。如果把配置放得太宽,出现「CORS 配置错误」,第三方网站就可能读取到已登录用户的数据。本文从防御视角讲解它的原理,以及安全的配置方法(白名单、不要反射 Origin、不要把 * 和认证信息同时使用)。

发布于 2026-06-11 更新于 2026-06-11 1 分钟阅读

「给 API 加上 Access-Control-Allow-Origin 之后就能用了,但这样安全吗?」——CORS 并不是「加上就 OK」,关键在于把许可的对象收紧。本文讲解它的原理和安全的配置方法(不会写出攻击步骤)。

先讲原理

浏览器有一条同源策略:其他源的 JS 不能擅自读取其他网站的响应。CORS 就是用来把这条规则的例外只对服务器明确许可的对象打开的机制。

响应头含义
Access-Control-Allow-Origin允许哪个源读取响应
Access-Control-Allow-Credentials是否允许带 Cookie 等认证信息的通信
Access-Control-Allow-Methods / -Headers允许的 HTTP 方法/头

关键在于,CORS 是属于「放宽限制」那一侧的机制。放宽的方式一旦出错,本不该被读取的数据就会被第三方读到。

哪些配置是危险的

危险的配置(容易犯)

  • 把请求的 Origin 原样反射回去并予以许可
  • Access-Control-Allow-Origin: *同时允许认证信息
  • 把不必要的 API 也大范围地对其他源开放

安全的配置

  • 白名单(只放可信任的固定源)
  • 其他一律默认拒绝
  • 带认证信息时不用 *,而指定具体的源
攻击者网站的 JS 向你的 API 发起请求(用户处于登录状态)
↓ 服务器不加判断地许可了 Origin(配置错误)
浏览器允许读取响应=个人信息/令牌被交到攻击者网站手里
配置太宽时,攻击者网站的 JS 就能借用用户的登录状态读取到 API 的响应。

安全配置的基本原则

1

采用白名单方式(最重要)

只许可事先确定的可信任的源,其他一律拒绝(默认拒绝)。不要「先全部许可了再说」。
2

不要不加判断地反射 Origin

不要把请求里的 Origin 原样 echo 到 Access-Control-Allow-Origin只有与白名单比对一致时才返回。
3

带认证信息时不要用 *

带 Cookie 等的通信中,不要把 Access-Control-Allow-Origin: *Allow-Credentials: true 同时使用。要指定具体的源
4

把开放范围降到最小

只把确实需要对其他源公开的端点作为对象。不要大范围开放。配置可以用安全响应头诊断等来确认。

本站的观点:CORS 不是「防守」,而是「放宽方式」。要收紧放宽的对象

一个常见的误解是「加上 CORS 头就安全了」。恰恰相反,CORS 是属于「放宽」浏览器限制那一侧的机制。所以安全的诀窍与其说是「怎么加」,不如说是「把对谁、开放到什么程度收到最小」。本站建议把可以被外部读取的数据和不可以的数据区分开,采取默认拒绝、只用白名单打开例外的方针。另外,让「响应会被读取」这一前提整个崩塌的 XSS,以及瞄准状态变更的 CSRF 是另一类漏洞,所以单靠 CORS 并不能守住全部。

延伸阅读

FAQ

QCORS 是干什么用的机制?
A

浏览器有一条「同源策略」:另一个源(网站)的 JavaScript 不能擅自读取其他网站的响应。CORS(Cross-Origin Resource Sharing)就是用来把这条规则的例外「只对服务器明确许可的对象」打开的机制。它通过 Access-Control-Allow-Origin 等响应头,声明允许哪些源读取响应。

QCORS 配置错误会引发什么?
A

如果许可放得太宽,攻击者网站的 JavaScript 就可能读取到用户已登录的 API 响应。典型例子是:把请求的 Origin 原样反射回去并予以许可,或者把 Access-Control-Allow-Origin 设为 * 的同时还允许认证信息(Cookie 等)。结果就是个人信息或令牌可能被交到第三方网站手里。

Q安全配置的基本原则是什么?
A

就是「白名单方式」。只许可事先确定的、可信任的源,其他一律拒绝(默认拒绝)。不要不加判断地反射请求里的 Origin。在带认证信息的通信中,Access-Control-Allow-Origin 不要用 *,而要指定具体的源。最根本的是,只把确实需要对其他源公开的端点作为对象。