深入解析同源策略

深入解析同源策略

💡 原文英文,约1900词,阅读约需7分钟。
📝

内容提要

同源策略要求协议、域名、端口一致,用于限制跨源读取,防止CSRF等攻击,但会导致Canvas污染、iframe访问受限和Ajax失败。解决方案包括CORS、反向代理和postMessage,其中CORS需处理预检请求与跨源Cookie。

🔎

延伸解读

同源策略的本质:只读访问

文章指出,同源策略限制跨源读取,但允许通过链接、表单、脚本等标签加载资源。这些方式只能读取数据,不能修改。例如,iframe 可以显示页面但无法操作其内容;表单提交会跳转,无法获取返回数据;Ajax 请求虽发送成功,但浏览器拦截响应,使开发者无法读取。理解这一点有助于明白为何某些跨源操作被允许,而另一些被禁止。

CORS 预检请求的作用

对于非简单请求,浏览器会先发送 OPTIONS 预检请求,询问服务器是否允许实际请求。服务器通过 Access-Control-Allow-Methods 等响应头告知允许的方法和头部。预检通过后,浏览器才发送实际请求。这样可以在请求到达服务器前拦截,避免危险操作。简单请求则直接发送,但若响应头配置不当,仍会报跨源错误。

跨源 Cookie 的额外要求

即使 CORS 允许跨源读取,携带 Cookie 仍需额外配置。fetch 默认不发送跨源 Cookie,需设置 credentials: 'include'。服务器需设置 Access-Control-Allow-Credentials: true,且 Access-Control-Allow-Origin 不能为 *,必须指定具体源。Cookie 需设置 SameSite=None 和 Secure,并必须使用 HTTPS。Chrome 80 后 SameSite 默认为 Lax,可能导致跨源 Cookie 不

解决跨源问题的其他途径

除了 CORS,文章提到反向代理和 postMessage。反向代理将跨源 API 和前端文件整合到同域,开发时可用 Webpack devServer.proxy 或 Vite 的 Server Options,生产环境常用 nginx。postMessage 用于不同窗口间通信,发送时需指定 targetOrigin,接收时通过 event.origin 验证来源,确保安全。这些方法可作为 CORS 的补充或替代。

❓

Q&A

同源策略中的“同源”具体指什么?

同源要求协议、主机(域名)和端口三者完全一致。例如 http://example.com:80 中,协议是 http,主机是 example.com,端口是 80。

同源策略会带来哪些常见的限制?

主要限制包括:Canvas 被污染后无法读取图像数据;无法访问 iframe 内部的大部分信息;Ajax 跨源请求会失败。

为什么同源策略允许通过 <script>、<img> 等标签加载跨源资源?

因为这些方式只能读取数据,不能修改数据,即“只能看不能碰”。它们都是只读访问,无法操作获取到的内容。

同源策略存在的目的是什么?

主要是为了防止跨站请求伪造(CSRF),防止主机随意操作 iframe,以及禁止客户端随意编辑非源站的图片、音频和视频文件。

CORS 协议是如何工作的?

CORS 是基于 HTTP 的协议,通过请求和响应头协商跨源访问。对于非简单请求,会先发送 OPTIONS 预检请求,服务器返回允许的配置,浏览器判断是否发送实际请求,实际请求的响应头也会包含 CORS 配置。

使用 CORS 时如何处理跨源 Cookie?

需要设置 credentials: 'include',服务器需添加 Access-Control-Allow-Credentials 并指定具体 Origin(不能为 *),Cookie 需设置 SameSite=None 和 Secure,且必须使用 HTTPS。

除了 CORS,还有哪些解决跨源问题的方法?

可以使用反向代理(如 Webpack devServer.proxy、Vite 的 Server Options 或 nginx)将跨源 API 整合到同域;也可以使用 postMessage 进行不同窗口间的数据交换;WebSocket 可绕过同源策略但服务器负载高;JSONP 也是一种方式。

🏷️

标签

➡️

继续阅读