不再学AJAX了!(三)跨域获取资源 ① - 同源策略

咱们以前提到过,AJAX技术使开发者可以专一于互联网中数据的传输,而再也不拘泥于数据传输的载体。经过AJAX技术,咱们获取数据的方式变得更加灵活,可控和优雅。数据库

可是AJAX技术并非一把万能钥匙,互联网中的数据隐私和数据安全(例如你的银行帐号和密码)也很是重要,为了保护某些用户数据的隐私与安全,浏览器使用“同源策略”限制了AJAX技术获取数据的范围和能力。但在一些合理的场景中,咱们又不得不想办法绕过同源策略,实现跨域请求资源。所以“跨域技术”一直成为开发者们经久不衰的讨论话题。segmentfault

在“跨域获取资源”这一主题中,咱们将围绕“同源策略”和“跨域”两大主题展开,不但讲述它们是什么,更说明了为何要这么作。相信你在读完该主题下的两篇文章后,必定会对这两大主题有一个清晰,系统的认识。跨域

须要提早声明的是,本主题下的文章并不会像众多相同主题的文章同样罗列出全部的跨域技术,而只会捡最主流的四种进行讲解。由于我并不打算写“教你如何跨域”这样类型的文章。浏览器

让咱们开始吧。安全

同源策略

整个互联网世界的数据要么存储在服务端(即服务器,如数据库,硬盘等)中,要么存储在客户端(即浏览器,如cookie,LocalStorage,sessionStorage)中。互联网数据的传输实际上就是客户端与服务端之间的交互。服务器

而所谓的数据隐私与安全保护,说白了就是数据拥有者对数据索取者发出警告:“不是你的你别动”。cookie

搞清了这个原则,咱们就很容易明白,若是你在客户端,而且想要获取服务端数据,你首先须要经过服务器端的验证,证实你有权限获取数据(例如“登陆”),而若是你在服务端,想要获取客户端的某些数据,你一样须要客户端经过某些方式验证你有资格获取相应的数据资源。session

那么上面提到的“某些方式”是什么呢?其中最重要的就是咱们今天的主题之一 -- 浏览器的“同源策略”。dom

浏览器的“同源策略”

浏览器所遵照的“同源策略”是指:限制不一样源之间执行特定操做。这涉及到两个问题:什么是“”?,以及“特定操做”是指什么?网站

让咱们停下来解释一下这个概念:

  1. 一个协议域名端口三部分组成,这三者任一一个不一样都会被浏览器识别为不一样的源;
  2. 上文所提到的特定操做是指:

    • 读取 Cookie,LocalStorage 和 IndexDB;
    • 获取 DOM 元素;
    • 发送 AJAX 请求;

在搞清了同源策略的概念以后,让咱们看看浏览器是出于怎样的考虑,一直坚守着同源策略:

为何要有“源”的概念?

由于不一样的源,大多数状况下就意味着它们在互联网中归属于不一样的站点(或是被用做不一样的用途)。也就是说它们是不一样的项目,有不一样的文件根目录,那么它们的数据也不该该共享也就理所应当了,不然数据的隐私和安全也无从谈起。不过请注意,我上面所说的话是基于“不一样源就彼此不相干”的假设,这其实存在一些问题,咱们以后会提到。

为何不能执行“特定操做”?

这个须要咱们假设,若是咱们想作一些“坏事”,而且浏览器容许咱们执行这些“特定操做”,咱们做为“坏人”能作什么:

首先,因为不少网站使用浏览器存储用户的用户名和密码,那么咱们即可以在A域中(咱们在服务器上托管的网站)读取任意来访用户的全部Cookie信息(没有同源策略的保护,该用户全部网站的Cookie记录都是透明的),咱们就能够利用这些Cookie信息假装成来访用户作任何事,而在现实世界,出于同源政策的保护,咱们只能访问用户该域下的Cookie信息,也就是说,咱们只能访问咱们本身设置的Cookie信息。

其次,若是咱们可以获取不一样域下的DOM元素,咱们就能够经过<iframe>标签在咱们的A域网站上引入B域网站,而后诱使用户在B域网站操做,因为咱们可以跨域获取DOM元素,所以咱们能够操做B域网站的DOM结构,用户输入的一切信息,以及用户操做的DOM元素就都在咱们的掌控之中了。这正是同源策略想要规避的安全隐患。

最后,为何要禁止不一样源的站点发送AJAX请求呢?这个提及来有些复杂,咱们首先要对Cookie的运做原理有一个大体的了解:

当咱们设置Cookie时,除了存放键值对形式的数据信息外,浏览器还会为Cookie的一些属性填充默认值(咱们也能够手动修改这些属性的值)。在这些属性中,咱们须要关注domainpath两个属性,它们一个表明域名,一个表明路径,二者加起来构成了一个肯定这条Cookie什么时候被调用和访问的URL。与此同时,浏览器本身维护的Cookie文件中也会添加这一条新建立的Cookie数据。

当咱们在浏览器中发送HTTP请求时,浏览器首先会检查请求地址并在本身所维护的Cookie文件中寻找匹配的Cookie信息,将其添加到请求头中的Cookie属性内,而后向服务器发送请求。请注意,这个自动添加相应Cookie信息的过程是浏览器本身偷偷帮咱们作到的,也就是说,咱们本身没法控制这个过程。

下面重点来了,当咱们的HTTP请求到达服务器时,服务器返回的响应中,响应头会原封不动的返回咱们发送给他的Cookie信息。嗅到危险的味道了吗?咱们虽然不能在发送请求前得到Cookie信息,可是在发送请求后,咱们仍是可以得到用户的Cookie!

让我再进一步解释一下这和AJAX有什么关系,假设咱们在本身的服务器上托管了站点A,并在其中隐藏了一段脚本,每一个登陆站点A的人都会自动发送AJAX请求至站点B(提示:站点B是一个银行),那么在没有浏览器同源策略的状况下,若是站点A中的访问者刚好有Cookie中保留站点B信息的用户,经过AJAX请求返回的响应头,咱们同样能够拿到这位用户的站点B Cookie,从而假装成用户在站点B登陆,作一些违法乱纪的事情(CSRF攻击便是利用了这个原理,只不过出于同源策略限制,并不能经过发起AJAX的方式)。

虽然有些费劲,可是如今你应该明白为何同源策略要阻止跨域发送AJAX了吧?(我终于将这个概念说清楚了,真是费了很多力气 ?)

想要了解更多关于Cookie的信息,能够参考这篇文章

同源策略的表现

看看咱们的任务清单,咱们解释了什么是同源策略以及浏览器为何要有同源策略,但至今为止,咱们还未曾看到,在浏览器同源策略的限制下,当咱们想要获取跨域Cookie,DOM结构和发送AJAX时,咱们是如何被“拒绝”的。

首先,咱们在一个域下只能读取该域下的Cookie值。当咱们在页面中使用<iframe>标签时,咱们获取对应DOM节点下只有一个空空的#document节点,并无额外的DOM信息。

893617-20171108143254122-1046163796.png

而对于AJAX,浏览器其实并无阻止咱们向不一样域发送请求,其阻止的是此次请求的响应,也就是说服务端其实接收到了此次请求,只是响应被浏览器解析时被浏览器发现违背了同源策略而被拒绝,此时,浏览器会在控制台中打印出一条错误信息。

893617-20171108145537997-1749515929.png

另外须要注意的是,对于XHR请求,实际上咱们在请求报头也不会看到相应的Cookie信息,这是由于CORS标准中作了规定,默认状况下,浏览器在发送跨域请求时,不能发送任何认证信息,好比cookiesHTTP authentication schemes。除非你显式的将xhr实例的withCredentials属性的值设置为true而且服务器端也容许客户端请求携带认证信息(即服务器端在响应头中设置了Access-Control-Allow-Credentials: true)。

要在跨域请求头中显示Cookie真是不容易对吧?

可是,等等!CORS标准是什么?

问得好,在下一篇以“跨域发送请求”为主题的文章中,咱们会详细谈到他。目前为止,你已经充分了解“同源策略”这个主题。Good Job!

如今让咱们先暂时休息一下,下一篇见 ?。

? Hey!喜欢这篇文章吗?别忘了在下方? 点赞让我知道。

相关文章
相关标签/搜索