讲透同源策略

讲透同源策略

💡 原文中文,约6300字,阅读约需15分钟。
📝

内容提要

同源策略要求协议、域名、端口一致,核心是限制非同源资源的读取,防止CSRF和iframe滥用。它限制Canvas读取、iframe访问和Ajax请求,但允许链接、脚本、图片等加载。跨域主要靠CORS,通过预检请求和响应头协商权限,并需处理跨域Cookie的SameSite、Secure等限制。其他方案包括反向代理、postMessage和JSONP。

🔎

延伸解读

同源策略的本质:只读限制

文章指出,同源策略并非完全禁止跨域资源,而是限制对非同源资源的读取和修改。例如,链接、脚本、图片等标签可以加载跨域资源,但只能获取只读数据,无法操作或修改。这种设计在安全性和可用性之间取得平衡,既防止恶意操作,又允许必要的资源引用。

CORS 预检请求的作用与流程

对于非简单跨域请求,浏览器会先发送 OPTIONS 预检请求,询问服务器是否允许实际请求。服务器通过 Access-Control-Allow-* 响应头返回许可条件,浏览器据此决定是否发送真实请求。预检机制能在请求到达服务器前拦截潜在危险操作,而简单请求则直接发送,但响应仍受 CORS 头限制。

跨域 Cookie 的额外要求

即使 CORS 协商成功,跨域携带 Cookie 仍需满足多项条件:fetch 需设置 credentials: 'include';服务器需返回 Access-Control-Allow-Credentials: true 且 Access-Control-Allow-Origin 不能为通配符;Cookie 必须设置 SameSite=None 和 Secure,且仅限 HTTPS。Chrome 80 后 SameSite 默认 Lax,导致跨域 Cookie 默认不发送,可能引发登录问题。

其他跨域方案与适用场景

除 CORS 外,反向代理可将跨域接口转为同域,适用于开发和生成环境;postMessage 用于不同 window 间通信,需验证 event.origin 确保安全;JSONP 利用脚本跨域,但已过时;WebSocket 可绕过同源策略,但服务器负荷大,不推荐替代 HTTP。开发者应根据场景选择合适方案。

❓

Q&A

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

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

同源策略主要限制了哪些操作?

同源策略限制非同源资源的读取,包括:Canvas 污染后无法读取图像数据、无法获取 iframe 内部绝大部分信息、Ajax 请求被拦截。

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

因为这些标签只能获取数据,不能修改数据,属于只读操作。同源策略的本质是保证非同源信息只读,所以允许这类加载。

CORS 协议是如何工作的?

CORS 是基于 HTTP 的协议,通过请求头和响应头协商跨域权限。对于非简单请求,浏览器先发送 OPTIONS 预检请求,服务器返回允许的源、方法、头等信息,浏览器判断后才发送真实请求。

处理跨域 Cookie 时需要注意哪些问题?

fetch 默认不携带跨域 Cookie,需设置 credentials: 'include';服务器需设置 Access-Control-Allow-Credentials 为 true,且 Access-Control-Allow-Origin 不能为 *,必须是具体源;Cookie 需设置 SameSite=None 和 Secure,且必须使用 HTTPS。

除了 CORS,还有哪些解决跨域的方法?

反向代理(如 nginx、Webpack devServer.proxy)、postMessage(用于不同 window 间通信)、JSONP(已过时)、websocket(可绕过但服务器负荷大)。

🏷️

标签

➡️

继续阅读