我们之前提到过,AJAX技术使开发者能够专注于互联网中数据的传输,而不再拘泥于数据传输的载体。通过AJAX技术,我们获取数据的方式变得更加灵活,可控和优雅。

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

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

需要提前声明的是,本主题下的文章并不会像众多相同主题的文章一样罗列出所有的跨域技术,而只会捡最主流的四种进行讲解。因为我并不打算写“教你如何跨域”这样类型的文章。

让我们开始吧。

同源策略

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

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

搞清了这个原则,我们就很容易明白,如果你在客户端,并且想要获取服务端数据,你首先需要通过服务器端的验证,证明你有权限获取数据(例如“登录”),而如果你在服务端,想要获取客户端的某些数据,你同样需要客户端通过某些方式验证你有资格获取相应的数据资源。

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

浏览器的“同源策略”

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

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

  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了吧?(我终于将这个概念说清楚了,真是费了不少力气

再也不学AJAX了!三跨域获取资源 ① - 同源策略的更多相关文章

  1. HTML5 Web缓存和运用程序缓存(cookie,session)

    这篇文章主要介绍了HTML5 Web缓存和运用程序缓存(cookie,session),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. 关于h5中的fetch方法解读(小结)

    这篇文章主要介绍了关于h5中的fetch方法解读(小结),fetch身为H5中的一个新对象,他的诞生,是为了取代ajax的存在而出现,有兴趣的可以了解一下

  3. ios – 如何在Swift中手动为UIWebView设置Cookie

    我需要在swift中为webview设置一个cookie.我找到了一个解决方案,但它是针对objective-c的.如何在Swift中做到这一点?

  4. 通过在iOS中处理cookie来维护会话信息

    我是iOS开发的新手.我正在使用NSURLSession来管理会话信息.下面是我用来调用任何服务器API的示例代码,我的申请流程是,如果没有登录–>登录(呼叫登录api)Else转到主屏幕并调用其他API.我的问题是,一旦从内存中删除应用程序,会话信息就不会被维护,我不得不再次调用Login.我的要求就像Facebook一样,用户只需登录一次,并且在下次应用程序启动时保持会话.编辑:我想我必须通过

  5. ios – 以http无效的自定义URL方案开头

    我在应用程序中使用了自定义URL方案.我成功地从safari重定向到我的应用程序.就像我已经制作了URL方案“appname”.请检查http://prntscr.com/2cjx0p.我需要使用像iosurlredirectfrommailtoapp这样的解决方案,但我不确定如何设置cookie.我发现我必须首先在我的应用程序中为服务器“http://myappname.com”设置一个cook

  6. 在iOS 8.4上清除WKWebView的Cookie

    另一个想法是使用自定义的WKProcesspool子类手动管理cookie.我相信这是Firefox如何管理任何cookie问题.

  7. ios – 在302重定向之后,AVPlayer无法为同一个域发送cookie

    有没有办法解决这个问题?请分享你的想法.解决方法制作一个演示该问题的示例,提交错误报告.然后创建一个提到雷达的DTS事件,并且您正在寻找一个解决方案,以便您认为是一个错误.这打开了两种可能性:>工程师可以确认错误–如果不知道他们会修复它,如果它是重复的,您可以请求原始状态信息>DTS具有足够的知识,有能力查询实际的AV工程师如何解决这个问题这样你就可以花更少的时间找到可能不会得到任何其他答案的地方.

  8. ios – AFNetworking自动持久化Cookie

    在ThisQuestion中说,AFNetworking在后台自动处理cookies,但是在Previous问题中,我遇到麻烦,在登录时在PHP服务器上保持会话.一旦关闭的应用程序,并回到会议已经没了.答案是保持像这样的cookie来解决问题:当我尝试做这样的事情时,这给我一个应用程序崩溃.当我登录时,我设置了NSUserDefault:这是错误的使用方法吗?谢谢.解决方法使用以下内容,这是保存和加载适用于我的Cookie的正确方法:希望有帮助!

  9. ios – WKWebView Cookie存储位置

    希望苹果能够在最新的更新中解决这个问题.

  10. ios – SFSafariViewController cookie

    据我所知,从iOS9开始,您应该能够使用SFSafariViewController读取cookie.如果我使用以下内容在JS中的页面上设置cookie:如果我做:cookiesArray总是空的.如果我使用传统的UIWebView我得到了我期待的cookie.我有什么想法可能做错了吗?解决方法SFSafariViewController基本上是一个Safari进程,在你的应用程序之外运行.您的应

随机推荐

  1. xe-ajax-mock 前端虚拟服务

    最新版本见Github,点击查看历史版本基于XEAjax扩展的Mock虚拟服务插件;对于前后端分离的开发模式,ajax+mock使前端不再依赖后端接口开发效率更高。CDN使用script方式安装,XEAjaxMock会定义为全局变量生产环境请使用xe-ajax-mock.min.js,更小的压缩版本,可以带来更快的速度体验。

  2. vue 使用 xe-ajax

    安装完成后自动挂载在vue实例this.$ajaxCDN安装使用script方式安装,VXEAjax会定义为全局变量生产环境请使用vxe-ajax.min.js,更小的压缩版本,可以带来更快的速度体验。cdnjs获取最新版本点击浏览已发布的所有npm包源码unpkg获取最新版本点击浏览已发布的所有npm包源码AMD安装require.js安装示例ES6Module安装通过Vue.use()来全局安装示例./Home.vue

  3. AJAX POST数据中文乱码解决

    前端使用encodeURI进行编码后台java.net.URLDecoder进行解码编解码工具

  4. Koa2框架利用CORS完成跨域ajax请求

    实现跨域ajax请求的方式有很多,其中一个是利用CORS,而这个方法关键是在服务器端进行配置。本文仅对能够完成正常跨域ajax响应的,最基本的配置进行说明。这样OPTIONS请求就能够通过了。至此为止,相当于仅仅完成了预检,还没发送真正的请求呢。

  5. form提交时,ajax上传文件并更新到&lt;input&gt;中的value字段

  6. ajax的cache作用

    filePath="+escape;},error:{alert;}});解决方案:1.加cache:false2.url加随机数正常代码:网上高人解读:cache的作用就是第一次请求完毕之后,如果再次去请求,可以直接从缓存里面读取而不是再到服务器端读取。

  7. 浅谈ajax上传文件属性contentType = false

    默认值为contentType="application/x-www-form-urlencoded".在默认情况下,内容编码类型满足大多数情况。在这里,我们主要谈谈contentType=false.在使用ajax上传文件时:在其中先封装了一个formData对象,然后使用post方法将文件传给服务器。说到这,我们发现在JQueryajax()方法中我们使contentType=false,这不是冲突了吗?这就是因为当我们在form标签中设置了enctype=“multipart/form-data”,

  8. 909422229_ajaxFileUpload上传文件

    ajaxFileUpload.js很多同名的,因为做出来一个很容易。我上github搜AjaxFileUpload出来很多类似js。ajaxFileUpload是一个异步上传文件的jQuery插件传一个不知道什么版本的上来,以后不用到处找了。语法:$.ajaxFileUploadoptions参数说明:1、url上传处理程序地址。2,fileElementId需要上传的文件域的ID,即的ID。3,secureuri是否启用安全提交,默认为false。4,dataType服务器返回的数据类型。6,error

  9. AJAX-Cache:一款好用的Ajax缓存插件

    原文链接AJAX-Cache是什么Ajax是前端开发必不可少的数据获取手段,在频繁的异步请求业务中,我们往往需要利用“缓存”提升界面响应速度,减少网络资源占用。AJAX-Cache是一款jQuery缓存插件,可以为$.ajax()方法扩展缓存功能。

  10. jsf – Ajax update/render在已渲染属性的组件上不起作用

    我试图ajax更新一个有条件渲染的组件。我可以确保#{user}实际上是可用的。这是怎么引起的,我该如何解决呢?必须始终在ajax可以重新呈现之前呈现组件。Ajax正在使用JavaScriptdocument.getElementById()来查找需要更新的组件。但是如果JSF没有将组件放在第一位,那么JavaScript找不到要更新的内容。解决方案是简单地引用总是渲染的父组件。

返回
顶部