AJax技术

再也不学AJAX了(三):跨域获取资源②JSONP CORS

字号+ 作者:H5之家 来源:H5之家 2017-12-13 12:36 我要评论( )

浏览器的同源策略固然保障了互联网世界的数据隐私与数据安全,但是如果当我们需要使用AJAX跨域请求资源时,同源策略又会成为开发者的阻碍。在本文中,我们会简单

> 编程开发 > AJAX相关 >

再也不学AJAX了(三):跨域获取资源②JSONP & CORS 2017-12-06 16:42 出处:清屏网 人气: 

浏览器的“同源策略”固然保障了互联网世界的数据隐私与数据安全,但是如果当我们需要使用AJAX跨域请求资源时,“同源策略”又会成为开发者的阻碍。在本文中,我们会简单介绍需要跨域请求资源的两种情景,然后,详细解释目前主流的四种跨域请求资源方案。

让我们开始吧!

一、何时需要跨域

试想,当我们拥有多个站点,并且这些站点又经常共享相同的数据,那么为每个站点存储一份数据看起来就蠢透了。更好的方案是,我们建设一台静态资源存储服务器,然后让我们的所有站点都从这一台服务器上获取资源。很理想的方案,但是现实中,我们首要解决的问题便是浏览器的“同源策略”,别忘了,不同域之间无法通过AJAX技术获取资源。这是需要跨域获取资源的主要情景。

另外,站在互联网“开放,平等,自由”精神的角度上讲,如果所有人的数据都被设置为只有同域才能访问,那么互联网世界未免也太无聊了,如果我就是想要与更多的人分享我的数据,难道不应该有办法让我做到这一点吗?

当然有办法,下面我们就将一一解释当下主流的跨域请求资源方式。

二、跨域请求资源方案

我们将主要介绍以下四种跨域请求资源的方案,并逐一解释他们的原理,实用方式以及优缺点,希望你和我一样有耐心,耐心总是能带来回报:

  • 野路子出身却好用的方式:JSONP;
  • 官方推荐的跨域资源共享方案:CORS;
  • 使用HTML5 API:postMessage;
  • 抛弃HTTP,使用:Web Sockets;
  • 在开始下面的内容之前,我们首先需要强调一点, 无论是怎样的跨域资源获取方案,本质上都需要服务器端的支持 。跨域获取资源之所以能够成功,本质是服务器默许了你有权限获取相应资源。下面我们所运用的种种方式,实际上是客户端和服务端互相配合,绕过同源策略进行数据交互的工作,千万不要误以为掌握了下述技术后,我们就能成为一个黑客 ����‍♂️。

    (一)野路子出身却异常好用的方式:JSONP

    正如标题所描述的那样,JSONP技术是早期某个(些?)聪明的程序员发明的跨域资源获取方式,由于该技术的简单易用,逐渐变得越来越流行,最终成为经典的跨域获取资源方案。

    JSONP是“JSON with padding”的简写,我将其翻译为“被包裹的JSON”,当你看完这个章节,你一定会觉得这个名字相当贴切。

    让我们模拟一下当初想到JSONP技术的高手程序员是如何推理的:

    首先,我们应该清楚的认识到,浏览器的“同源策略” 只是阻止了通过AJAX技术跨域获取资源,而并没有禁止跨域获取资源这件事本身 ,正因如此,我们可以通过 <link> 标签, <img> 标签以及 <script> 标签中的 href 属性或 src 属性获取异域的CSS,JS资源和图片(虽然我们其实并不能读取这些资源的内容)。

    其次,我们知道(也许你不知道,但是,还记得吗,我在模拟那个高手程序员?) <script> 标签通过 src 属性加载的JS资源,实际上只是将JS文件内容原封不动的放置在 <scritp> 的标签内,并没有什么神奇之处!

    也就是说,如果我们的sayHi.js文件只有这样一段代码:

    // sayHi.js alert('Hi')

    当我们在HTML文件中,成功加载sayHi.js文件时,浏览器只不过是做了如下操作:

    <!-- 加载前 --> <script src="sayHi.js"></script> <!-- 加载后 (为了方便阅读,我格式化了代码)--> <script src="sayHi.js"> alert('Hi') </script>

    这意味着什么呢?这意味着被加载的文件与HTML文件下的其他JS文件共享一个全局作用域。也就是说, <scritp> 标签加载到的资源是可以被全局作用域下的函数所使用的!

    但是慢着!如果 <script> 标签加载到的一些数据并不符合JavaScript语法规定的 数据类型 ,JavaScript就无法处理这些错误不是吗?而且就算数据类型正常了,我们还应该将数据存储于一个 变量 内,然后调用这个变量...

    说的没错!不过我们其实已经离正确答案很近了。

    还记的我们这一方案的名称吗?JSONP!,也就是说我们已经约定好了数据的格式为JSON,这是JavaScript可以处理的数据类型,并且JSON格式的数据可以承载大量信息。那么有关 变量 的问题呢?这个回答则更巧妙些,因为我们会通过向服务器传入一个函数的方式,将数据变为函数的参数,让我们直接看看JSONP的使用方式:

    1. function handleResponse(response) { 2. alert(`You get the data : ${response}`) 3. } 4. const script = document.createElement('script') 5. script.src = '?callback=handleResponse' 6. document.body.insertBefore(script, document.body.firstChild)

    很容易看到,我们在1-3行中创建了一个函数,该函数用来处理我们将要获得的数据,该函数的参数 response 即是服务器响应的数据。在4-6行中我们所做的是利用JavaScript动态生成一个script标签,并将其插入HTML文档。但是注意第5行我们制定的src值,在URL末尾,我们有这样一段查询参数 callback=handleResponse ,callback的值正是我们先前创建的函数。

    事情开始变得有些令人困惑了,究竟发生了什么呢?我们如何通过上述代码最终实现跨域获取资源?

    答案就藏在服务端的代码中,当服务端支持JSONP技术时,会做如下一些设置:

  • 识别请求的URL,提取callback参数的值,并动态生成一个执行该参数值(一个函数)的JavaScript语句;
  • 将需要返回的数据放入动态生成的函数中,等待其加在到页面时被执行;
  • 此时该文件内容看起来就像这样:

    handleResponse(response) // response为被请求的JSON格式的数据

    因此,当资源加载到位,内容显示在script标签内时,浏览器引擎会执行这条语句,我们想要的数据就可以被我们以任何想要的方式处理了。真不可思议!

    你现在知道为什么这项技术被命名为JSONP了吧?那个“padding”指的就是我们的“callback”函数,真是恰如其名。

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    • 通过Ajax方式上传文件,使用FormData进行Ajax请求

      通过Ajax方式上传文件,使用FormData进行Ajax请求

      2017-12-13 14:55

    • PHP ajax 分页类代码

      PHP ajax 分页类代码

      2017-12-12 18:14

    • Access-Control-Allow-Origin与Ajax跨域解决方法

      Access-Control-Allow-Origin与Ajax跨域解决方法

      2017-12-12 18:00

    • 从零开始学习jQuery (六) AJAX快餐(10)

      从零开始学习jQuery (六) AJAX快餐(10)

      2017-12-12 09:22

    网友点评
    3