javascript.info 网络专题:为什么跨域请求需要 Origin 头而不是只靠 Referer
发布时间:2026/10/8 13:05:43 作者:尧图编辑部 阅读量:1,286

文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载HTTP 的Referer头携带了发起请求的完整页面地址信息量似乎比Origin更丰富那么 CORS 体系为什么还要单独设计一个Origin头本篇基于 javascript.infoModern JavaScript Tutorial仓库中 5-network/05-fetch-crossorigin 章节的思考题及其官方解答深入剖析Origin与Referer的本质差异、Referer不可靠的种种场景并顺带串联起 CORS 中Origin头从发送到校验的完整链路。读完你将掌握为什么浏览器必须担保跨域请求中的Origin头、Referer在什么情况下会缺失或被篡改以及fetch的referrer/referrerPolicy/credentials选项如何与这两个头协同工作。问题背景一个请求同时携带Referer与Origin在原文档 task.md 中题目首先给出了一个非常常见的场景当从http://javascript.info/some/url发起对http://google.com的请求时浏览器实际发出的 HTTP 头大致如下Accept: */* Accept-Charset: utf-8 Accept-Encoding: gzip,deflate,sdch Connection: keep-alive Host: google.com Origin: http://javascript.info Referer: http://javascript.info/some/url可以看到Referer和Origin同时出现Referer携带的是完整 URL包含路径/some/url而Origin只携带协议 域名 端口三元组不含路径。于是题目提出了两个核心问题既然Referer信息量更大连路径都有为什么还需要单独的OriginReferer或Origin是否可能缺失或者携带不正确的内容这两个问题正是理解浏览器安全模型中来源origin概念的关键入口。答案核心Referer并不可靠Origin才是浏览器担保的官方解答 solution.md 开门见山需要Origin是因为Referer有时会缺失。逐一拆解原因如下。场景一HTTPS 页面 fetch HTTP 页面时没有Referer当从一个 HTTPS 页面更安全发起fetch请求到一个 HTTP 页面安全性较低时浏览器会出于隐私保护原则不发送Referer头。这是更安全的协议降级访问不安全的协议时浏览器主动采取的抑制策略防止把高安全页面的完整地址泄露到明文信道上。此时服务端如果想判断请求来源Referer头根本不存在无法作为依据而Origin头依然会被发送对于跨域请求浏览器始终添加Origin。场景二CSP内容安全策略可以禁止发送Referer页面可以通过 HTTP 头Referrer-Policy以及更广泛意义上的 Content Security Policy 相关机制来声明禁止发送Referer。比如 Fetch API 章节中提到的页级默认策略可以整体关闭Referer此时所有请求都不会携带它。场景三fetch自己可以删除甚至伪造Referer如 Fetch API 章节所展示fetch提供了专门控制Referer的选项// 完全不发送 Referer 头 fetch(/page, { referrer: // 空字符串 无 Referer 头 }); // 设置当前 origin 内任意 URL 作为 Referer fetch(/page, { referrer: https://javascript.info/anotherpage // 仅限当前 origin 内部 });也就是说Referer的值可以被页面脚本主动改写虽然只能限定在当前 origin 内它对服务端而言并不可信。规范层面Referer本来就是可选头在 HTTP 规范中Referer是一个可选optional的请求头服务端不能假定它一定会出现。综合以上四点结论非常清晰Referer既可能缺失、也可能被策略抑制、还可能被脚本改写因此完全不适合作为跨域安全决策的唯一依据。Origin的诞生浏览器对跨域请求的硬性担保正是因为Referer不可靠标准引入了Origin头。二者的关键区别在于谁来保证它的正确性Referer的内容由页面/浏览器尽力而为地填写可以缺失、可以被子资源加载策略省略、可以在受限范围内被脚本替换Origin则在跨域请求时由浏览器强制写入例如从https://javascript.info/page请求https://anywhere.com/request时请求头必然包含Origin: https://javascript.info脚本无法通过fetch选项删除或修改它——这一点在 fetch 基础章节的禁用请求头forbidden headers列表中体现得很直接Origin、Referer等头被列入浏览器独占控制清单脚本无权设置。fetch 基础章节列出的浏览器独占头包括Origin、Referer、Cookie、Host、Content-Length、Connection等。这些头确保 HTTP 的恰当与安全因此完全由浏览器控制——Origin的担保属性正来源于此。Origin与 CORS 的关系被校验的主角理解了Origin的可靠性就明白了为什么整个 CORSCross-Origin Resource Sharing跨源资源共享机制以Origin为判断核心。跨域请求章节中给出的完整流程是浏览器发起跨域请求时自动附上Origin头此时服务端收到的是一个由浏览器担保的、准确的来源服务端检查Origin若同意放行则在响应中返回Access-Control-Allow-Origin值可以是具体 origin如https://javascript.info或通配符*浏览器作为受信任的中介检查响应头存在且匹配Access-Control-Allow-Origin则允许 JavaScript 读取响应否则报错。如上图所示xhr-another-domain.svg跨域请求带Origin头发出响应若带Access-Control-Allow-Origin*或具体 origin则成功否则失败。这里Origin头的准确性是整条安全链路的基石——它由浏览器担保写入服务端可以放心据此做白名单校验。凭据Credentials场景Origin必须精确而非*跨域请求章节进一步指出一个细节当请求携带凭据cookie 或 HTTP 认证时Access-Control-Allow-Origin禁止使用*必须返回与请求Origin完全一致的精确值且需额外配合Access-Control-Allow-Credentials: true。例如200 OK Access-Control-Allow-Origin: https://javascript.info Access-Control-Allow-Credentials: true这是额外的安全措施——确保服务端明确知道自己在信任谁。而 JavaScript 侧要发送凭据则需在fetch中显式声明fetch(http://another.com, { credentials: include // 默认 same-origin跨域不带凭据 });credentials选项的完整取值说明见 Fetch API 章节same-origin为默认、include总是携带、omit从不携带。之所以默认跨域请求不带凭据是因为带凭据的请求威力更大——它相当于让脚本以用户身份访问敏感信息因此必须由服务端显式授权。延伸referrerPolicy与Referer的九种取值既然Referer可以被精细控制浏览器也提供了完整的策略体系。 Fetch API 章节的referrerPolicy选项按同源请求 / 跨源请求 / HTTPS→HTTP 降级请求三种类型定义了发送规则核心取值如下值同源跨源HTTPS→HTTPno-referrer---no-referrer-when-downgrade完整完整-originoriginoriginoriginorigin-when-cross-origin完整originoriginsame-origin完整--strict-originoriginorigin-strict-origin-when-cross-origin默认完整origin-unsafe-url完整完整完整默认值strict-origin-when-cross-origin的策略是同源发完整Referer跨源只发 origin 部分HTTPS→HTTP 降级请求则完全不发——这与本任务答案中HTTPS 访问 HTTP 时Referer缺失的现象完全一致也解释了为什么依赖Referer不可靠。实际应用举例若站点存在不希望被外部知道路径结构的敏感 URL如https://javascript.info/admin/secret/paths可以统一设置fetch(https://another.com/page, { referrerPolicy: origin-when-cross-origin // 跨源时 Referer 只发 https://javascript.info });另外该策略并非fetch独有页面可通过Referrer-PolicyHTTP 头设置全局默认也可通过a relnoreferrer对单个链接生效。小结为什么需要Origin回到本任务的最终答案可以归纳为一张对照表维度RefererOrigin携带内容完整 URL含路径仅 origin协议域名端口规范地位可选头可缺失跨域请求时浏览器强制附加可被 CSP / 策略抑制是否可被脚本删除或修改是referrer/referrerPolicy选项限当前 origin 内否浏览器独占头属于 forbidden headers对服务端的意义参考信息不可依赖可信来源CORS 白名单校验依据Origin存在的根本原因就是Referer不可靠规范允许它缺失、HTTPS→HTTP 降级请求时浏览器主动省略它、CSP 可以禁止它、fetch还能删除或改写它。而Origin由浏览器在跨域请求时强制写入且脚本无法干预服务端可以放心地用它来决定是否放行跨域请求、是否携带凭据、以及Access-Control-Allow-Origin该精确返回哪个值。这既是 CORS 机制能成立的前提也是本任务最值得记住的安全设计思想。进一步阅读完整的 CORS 细节安全请求、preflight 预检、Access-Control-Expose-Headers等见 5-network/05-fetch-crossorigin/article.mdfetch全部选项见 5-network/06-fetch-api/article.md禁止脚本设置的头列表见 5-network/01-fetch/article.md。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐Pensieve网络请求分析为什么它不需要互联网连接Pensieve网络请求分析为什么它不需要互联网连接 在当今数据驱动的世界隐私和数据控制权成为越来越重要的议题。Pensieve作为一款本地优先的屏幕记录工pytorch-retinanet验证与评估mAP指标计算与可视化完整指南pytorch retinanet验证与评估mAP指标计算与可视化完整指南 pytorch retinanet是一个基于PyTorch实现的RetinaNetWindows 1 分钟搞定 iPhone USB 网络共享苹果驱动免装 iTunes 的终极避坑指南Windows 1 分钟搞定 iPhone USB 网络共享苹果驱动免装 iTunes 的终极避坑指南 深夜的机场候机厅手机电量只剩 10%Wi Fi 弱开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考