浅谈同源策略

网友投稿 684 2022-05-29

同源策略可能是现代浏览器中最重要的安全概念了,它在使得同一站点中各部分页面之间基本上能够无限制允许脚本和其他交互的同时,能完全防止不相关的网站之间的任何干涉。现在所有支持 JavaScript 的浏览器都会使用这个策略,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。

我们可以假设一个没有同源策略的场景:我打开了我自己的银行账户页面,称之为 A,之后,我又打开了另一个页面,我们称之为 B。如果 B 是一个恶意页面,那么在没有同源策略限制的前提下,它可以通过 Javascript 任意修改和访问 A 中的任何内容。

一、什么叫做同源

首先要厘清的是,怎么样的页面被称为同源的页面——如果两个页面的协议、端口以及域名都相同,那这两个页面就被称之为同源,如果其中有一项不同,那也将不会满足同源的定义。下面是以 http://store.company.com/dir/page.html 这个 URL 为源的一组例子:

将表格中所有的 URL 与 http://store.company.com/dir/page.html 相比较,我们可以看到:

第一条和第二条同时满足了协议、端口和域名相同的条件,所以是同源;

第三条因为使用的是 https 协议,协议不同,所以不是同源;

第四条因为使用了 81 端口,端口不同,所以不是同源;

第五条因为域名,也就是域名不相同,所以不是同源。

那么为什么会对于同源做出如此严格的限制呢,其实是否同源主要是为了防止两类事件:

限制跨源脚本的 APIs 的访问;

阻止跨源数据存储的访问。

简单来说就是防止一个恶意界面通过恶意请求去访问非同源的数据。在发起跨域请求的情况下,我们的浏览器会自动的去拒绝这些请求,即使这样的跨域请求通过了,其返回结果也会被浏览器拒绝。

二、跨源网络访问

同源策略会对于跨域的资源和数据的访问做出限制。其实在网上很多情况下我们都会需要加载不同源的资源,比如在个人网站中需要插入一张在公共图床的图片,这种情况下个人网站和公共图床上的图片必然是不同源的,但最后在页面上能成功的加载图片并且能够看到,这又是为什么呢?

首先,通常情况下同源策略控制跨域的请求会被分为三类:

跨域写操作( Cross-origin writes )-- 例如表单提交,通常是被允许的;

跨域读操作( Cross-origin reads )-- 例如可以读取嵌入图片的高度和宽度,通常是不被允许的;

跨域资源嵌入( Cross-origin embedding )-- 例如嵌入图片,通常是被允许的。

那么可能有哪些资源是可以被跨源嵌入的呢?

标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到;

标签嵌入 CSS。由于 CSS 的松散的语法规则,CSS 的跨域需要一个设置正确的 Content-Type 消息头;

嵌入图片;

@font-face 引入的字体。一些浏览器允许跨域字体( cross-origin fonts ),一些需要同源字体( same-origin fonts );