「给 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 也大范围地对其他源开放
安全的配置
- 白名单(只放可信任的固定源)
- 其他一律默认拒绝
- 带认证信息时不用
*,而指定具体的源
安全配置的基本原则
采用白名单方式(最重要)
不要不加判断地反射 Origin
Origin 原样 echo 到 Access-Control-Allow-Origin。只有与白名单比对一致时才返回。带认证信息时不要用 *
Access-Control-Allow-Origin: * 与 Allow-Credentials: true 同时使用。要指定具体的源。把开放范围降到最小
延伸阅读
FAQ
QCORS 是干什么用的机制?
浏览器有一条「同源策略」:另一个源(网站)的 JavaScript 不能擅自读取其他网站的响应。CORS(Cross-Origin Resource Sharing)就是用来把这条规则的例外「只对服务器明确许可的对象」打开的机制。它通过 Access-Control-Allow-Origin 等响应头,声明允许哪些源读取响应。
QCORS 配置错误会引发什么?
如果许可放得太宽,攻击者网站的 JavaScript 就可能读取到用户已登录的 API 响应。典型例子是:把请求的 Origin 原样反射回去并予以许可,或者把 Access-Control-Allow-Origin 设为 * 的同时还允许认证信息(Cookie 等)。结果就是个人信息或令牌可能被交到第三方网站手里。
Q安全配置的基本原则是什么?
就是「白名单方式」。只许可事先确定的、可信任的源,其他一律拒绝(默认拒绝)。不要不加判断地反射请求里的 Origin。在带认证信息的通信中,Access-Control-Allow-Origin 不要用 *,而要指定具体的源。最根本的是,只把确实需要对其他源公开的端点作为对象。