跨域
跨域是浏览器开发中对“页面 origin 与目标资源 origin 不同后受到 Same-Origin Policy 约束”的问题总称;Same-Origin 定义边界,CORS 则提供受控放行机制。
[!info] related notes
- 所属 MOC: 前端基础 MOC, 浏览器 JS MOC
- Origin 判定: Same-Origin
- 放行机制: CORS
- Cookie 边界: SameSite
- 安全关系: CSRF, XSS vs CSRF
跨域
一句话关系
“跨域”不是一套独立协议,更准确地说是:
当前页面与目标资源属于不同 origin,浏览器的同源安全边界开始影响脚本能做什么。
理解它需要同时放进三个概念:
- Origin:哪两个 URL 属于同一安全来源。
- Same-Origin Policy:默认隔离哪些跨源能力。
- CORS:服务器怎样允许特定跨源脚本读取 HTTP 响应。
第一步:先判断是否 Cross-Origin
origin 的核心是 scheme + host + port,具体判定见 Same-Origin。
例如 https://app.example.com 与 https://api.example.com 的 host 不同,因此 cross-origin。
第二步:不要把“跨源”理解成“网络请求发不出去”
浏览器安全模型常限制的是:页面中的脚本是否可以访问跨源对象或读取跨源响应。
网络是否能到服务器、服务器是否执行请求、浏览器是否允许 JS 读取结果,是不同层。
server 收到请求 ≠ frontend JavaScript 一定能读取 response。
这也是调试 CORS 时最重要的分层。
第三步:如果需要跨源 HTTP 读取,看 CORS
当页面确实需要调用另一个 origin 的 API,流程通常是:
- 浏览器发送带 Origin 的请求或 Preflight。
- API 按策略判断允许的 origin / method / headers。
- 服务端返回 Access-Control-Allow-* 响应头。
- 浏览器决定是否把响应暴露给 JavaScript。
完整机制见 CORS。
Preflight、credentialed request、Allow-Headers 等都属于 CORS 本体,不在本页维护第二份说明。
跨域不只等于 CORS
| 场景 | 主要机制 |
|---|---|
| JS fetch/XHR 读取跨源 HTTP response | Same-Origin Policy + CORS |
| 跨源 iframe DOM 访问 | Same-Origin Policy |
| iframe/window 通信 | postMessage + explicit origin checks |
| Cookie 是否跨站携带 | SameSite / Cookie rules |
| cross-origin isolated 环境 | COOP / COEP / CORP |
| 图片、script、style 等资源加载 | 对应资源类型的 fetch / CSP / CORS 规则 |
因此“跨域”是一个上位问题空间,不应该用一条 Access-Control-Allow-Origin: * 解释所有情况。
CORS 与 CSRF 不在同一轴
CORS 主要回答:浏览器是否允许某个 origin 的 JavaScript 读取响应。
CSRF 主要回答:浏览器是否会借用户已有凭证发出非预期请求。
所以:
- CORS 通过不代表已经完成 authentication / authorization。
- CORS 拒绝不代表请求绝对没有产生服务器副作用。
- Cookie、SameSite、CSRF Token 属于另一层安全设计。
详见 CORS 与 XSS vs CSRF。
一个调试模型
遇到“跨域报错”时依次确认:
- 当前 page origin 是什么?
- target origin 是什么?
- 真的是 cross-origin 吗?
- Network 中实际请求或 Preflight 是否发出?
- 服务端响应了哪些 CORS headers?
- 浏览器阻止的是请求、response exposure,还是 credential?
- 后续是否还有 authentication / authorization error?
这比“看到 CORS error 就直接改 nginx”更稳定。
学习检查
不看正文回答:
- “跨域”为什么更适合作为 synthesis,而不是一个独立浏览器协议?
- Origin、Same-Origin Policy、CORS 三者分别负责什么?
- 为什么跨源请求到达后端仍可能在前端表现成 CORS error?
- 为什么 CORS 不能解释所有 iframe、Cookie、资源加载的跨源问题?
- CORS 与 CSRF 分别在哪一条安全轴上?
- 给一个前端 app 调 API 子域的场景,按 origin → SOP → CORS → auth 四层分析。
- 遇到“跨域失败”,为什么第一步应该确认两个实际 origin,而不是直接修改响应头?