← [ BACK_TO_NOTES ]

CORS

CORS(Cross-Origin Resource Sharing)是浏览器与服务器通过 Origin、Access-Control-Allow-* 和可选 Preflight 协商,允许特定跨源脚本读取响应的 HTTP 机制;它放宽同源策略,但不替代认证和授权。

#concept #growing #frontend #browser #http

[!info] related notes

CORS

一句话定义

CORS 是服务器通过 HTTP 响应头告诉浏览器:

哪些跨源页面可以让自己的 JavaScript 读取这份响应。

它是对 Same-Origin / 同源策略 的受控放宽,不是服务器端身份认证。

最小模型

Browser page origin
        ↓
cross-origin request with Origin
        ↓
Server
        ↓
Access-Control-Allow-* response headers
        ↓
Browser decides whether JS may access response

关键点:

CORS 的执行者是浏览器。

服务器返回响应,但浏览器决定是否把响应暴露给前端 JavaScript。

Origin

跨源请求通常会携带:

Origin: https://app.example.com

服务器可以返回:

Access-Control-Allow-Origin: https://app.example.com

如果浏览器认为 policy 不匹配,前端脚本就不能正常读取响应。

Simple Request

部分满足特定方法、Header 和 Content-Type 条件的请求,不需要先做 CORS preflight。

浏览器可以直接发送实际请求,再根据响应中的 CORS header 判断是否把响应暴露给 JavaScript。

因此:

“被 CORS 拦截”不一定代表请求没有到达服务器。

这也是为什么有副作用的接口不能依赖 CORS 代替 CSRF/授权保护。

Preflight

对于需要额外权限确认的跨源请求,浏览器会先发:

OPTIONS /resource
Origin: https://app.example.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: authorization, content-type

服务器响应示例:

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, PUT
Access-Control-Allow-Headers: Authorization, Content-Type

浏览器根据这次协商决定是否继续实际请求。

Preflight 的核心不是“OPTIONS 很特殊”,而是:

浏览器在真正发出某类跨源操作前先询问服务器允许的 origin、method 和 headers。

Credentials

如果跨源请求需要 Cookie 等 credentials,前端通常需要显式启用 credentials,服务端也必须允许 credentials。

这时不能简单把:

Access-Control-Allow-Origin: *

与 credentialed CORS 混用;应返回允许的具体 origin,并正确配置:

Access-Control-Allow-Credentials: true

同时要记住:

  • CORS;
  • Cookie SameSite;
  • CSRF;
  • authentication;

是不同安全边界。

CORS 不解决什么

不等于 Authentication

CORS 允许:

某个 origin 的浏览器 JavaScript 是否可读取响应。

Authentication 回答:

当前请求是谁发的。

不等于 Authorization

即使 origin 被允许,也仍然要判断用户有没有访问具体资源的权限。

不等于 CSRF 防御

即使浏览器不允许攻击者 JavaScript 读取响应,某些跨站请求仍可能被发送。

CSRF 要看浏览器自动携带凭证、SameSite、CSRF Token、Origin 验证等另一套机制。

不是前端代码单方面可修

如果服务端没有正确返回 CORS policy,前端不能通过“加一个 Access-Control-Allow-Origin request header”修复。

常见响应头

Header作用
Access-Control-Allow-Origin允许哪个 origin
Access-Control-Allow-MethodsPreflight 允许哪些 methods
Access-Control-Allow-HeadersPreflight 允许哪些 request headers
Access-Control-Allow-Credentials是否允许 credentialed access
Access-Control-Expose-Headers哪些非 safelisted response headers 可被 JS 读取
Access-Control-Max-AgePreflight 结果可缓存多久

调试顺序

遇到 CORS error 时优先分层:

1. 请求 URL / Origin 是否符合预期
2. 是否发生 Preflight
3. OPTIONS 是否成功到达服务端
4. ACAO / Allow-Methods / Allow-Headers 是否匹配
5. 是否携带 credentials
6. Cookie SameSite / Secure 是否允许实际携带
7. 实际 API 是否又因为 auth / permission 被拒绝

不要把所有 “fetch failed” 都直接归因到 CORS。

学习检查

不看正文回答:

  1. CORS 的真正执行者是谁?
  2. 为什么 CORS error 不一定代表实际请求没有到达服务器?
  3. Simple Request 与需要 Preflight 的请求最大的流程差异是什么?
  4. Preflight 中 Origin、Access-Control-Request-Method、Access-Control-Request-Headers 分别在询问什么?
  5. credentialed CORS 为什么不能简单配 Access-Control-Allow-Origin: *?
  6. CORS、Authentication、Authorization、CSRF 分别回答什么不同问题?
  7. 为什么前端自己加 Access-Control-Allow-Origin request header 不能修服务器 CORS?
  8. 给一个带 Authorization header 的跨源 PUT 请求,画出 Preflight → Actual Request → Browser Exposure 的完整路径。
创建于 2026/9/30 更新于 2026/9/30
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本