最近在读 Rails 安全性相关的文章时,再一次接触了“同源策略”这个术语。当然不陌生,不然还怎么混,俗话说“没吃过猪肉,至少见过猪跑嘛”!
可是真心讲,我并没有真正理解他的内涵。秉持着一颗孜孜不倦,求索不断的心,我开始了探索“同源策略”本质内涵之路。
起码看了 30+ 的文章,Google 表示我就这么多资源了……
最终我获得了一些想要的东西,但是对“同源策略”的理解也并没有完全透测,苦恼😖
下面就跟大家分享下我的所得吧! 这是我认为还有用的文章:
http://yincheng.site/cross-domain/comment-page-1#comment-3307
http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
http://eleveneat.com/2015/05/22/Same-origin-policy-md/
http://bbs.csdn.net/topics/390716390
http://blog.csdn.net/shimiso/article/details/21830313
https://en.wikipedia.org/wiki/Same-origin_policy
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
Wiki 的解释:
In computing, the same-origin policy is an important concept in the web application security model. Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin. An origin is defined as a combination of URI scheme, hostname, and port number.[1][2] This policy prevents a malicious script on one page from obtaining access to sensitive data on another web page through that page's Document Object Model.
Mdn 的解释:
The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. It is a critical security mechanism for isolating potentially malicious documents.
百度的解释:
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
仔细研读之后发现百度的解释是屁话,Wiki 的解释不全面,而 MDN 话不多,但说的都是核心。
而我说的核心如是:document or script loaded from one origin. resource from another origin
下面分别解释这两个核心:
document or script loaded from one origin
Document怎么操作另外一个 origin 的资源呢?
借用阮一峰博文的例子:
父窗口下有一个 iframe 窗口,如果父窗口的 dom 想去拿 iframe 窗口的 dom 会报错,反之亦然:
document.getElementById("myIFrame").contentWindow.document
// Uncaught DOMException: Blocked a frame from accessing a cross-origin frame.
上面命令中,父窗口想获取子窗口的 DOM,因为跨源导致报错。 反之亦然,子窗口获取主窗口的 DOM 也会报错。
window.parent.document.body // 报错
Script 怎么去操作另外一个 origin 的资源呢?
除了 Ajax 我还没找到其他的例子: 这是我自己做的一个实验,我启动一个 local server,然后通过 ajax 向我的 heroku 服务器发送请求:
<script>
url = "https://daily-plan.herokuapp.com";
document.cookie = "version=1;";
$.ajax({
method: "GET",
url: url,
xhrFields: {
'withCredentials': true
},
success: function(data){
document.write(data);
}
})
</script>
Error Message:
XMLHttpRequest cannot load https://daily-plan.herokuapp.com/. Redirect from 'https://daily-plan.herokuapp.com/' to 'https://daily-plan.herokuapp.com/plans' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access.
通过上面的两个例子我们可以引申出第二个要点: resource from another origin
什么算是一个 origin 的资源? 从之上的例子可以看出来,DOM 算是一类,Ajax 返回的数据算是一类 (这一类包含 DOM,当然也包含像是 JSON 格式的数据),还有一种这里没有举例的就是 Cookie。
关于 Cookie,上面 Ajax 的例子也同时验证了同源策略对 Cookie 的部分限制。
在我没有设置 'withCredentials': true 的时候,Ajax cross domain request 没有带任何的 cookie(local domain or heroku domain);而设置之后同样的 request 带上了 heroku domain 下的 cookie。
还有一些比较亮眼的结论是:
同源策略并没有限制请求的发送,仅仅是阻隔了响应的获取(参见:http://yincheng.site/cross-domain/comment-page-1#comment-3307)
在浏览器中,script, img, iframe, link 等标签都可以加载跨域资源,而不受同源限制,但浏览器限制了 JavaScript 的权限使其不能读、写加载的内容
我想说: 这目前是我整理得到的一些信息,以及自己的认识。我相信,肯定这不是全部。所以需要大家来完善下,帮助等多人理解这个关键的概念。毕竟,没有它我甚至不敢打开浏览器写这篇博文。