18910140161

理解跨域异步请求的JSONP

顺晟科技

2021-06-16 10:40:34

317

在开始之前,我们可能知道跨域问题的存在,在服务器上打开跨域请求让API实现跨域访问,甚至知道JSON-P,但可能只是基于阅读,不一定实践,所以JSON-P只是纸上谈兵,确实很多文章太“直接”。现在我试着用自己的方式解释,力求简洁中肯,同时整理自己的知识储备。

跨域

跨域被客户端理解为:为了安全起见,客户端(浏览器)特意设置了资源请求——“同源策略”的阈值,即不允许访问当前域下其他来源的资源,这个“域”或“源”在浏览器中表示为实际请求的URL。也就是说,浏览器不允许客户端在访问站点A时请求哔哩哔哩的资源.不同的域名,不同的IP,甚至不同的端口号都被认为是跨域的,除非服务器通过HTTP头标识告诉客户端释放这个限制。我们的目标是克服这个障碍。

JSON-P

JSON-P是绕过客户端同源策略的方法之一。实现跨域请求,需要前端技术协作,是对其他跨域异步请求方法的补充。不是技术,是技能。如上所述,浏览器设置了同源请求的阈值。但是,这个限制通常只针对cookie、本地存储、Ajax、跨域DOM获取等。并且对静态资源的请求没有限制,例如将CDN提供的引导库文件插入网站:

脚本src='//cdn . bootscs.com/bootstrap/4 . 0 . 0-alpha . 5/js/bootstrap . min . js '/脚本

src指向的脚本可以顺利下载执行。

JSON-P会通过这个特性绕过浏览器同源性的限制,配合后端返回处理过的内容,实现跨域请求。

实现

“JSON-P”全称是带Padding的JSON,形象地说明了获取JSON的方式(JSON数据是通过填充获得的)。我们用一个经典的例子来说明:

假设我们为a站后台设计一个API,允许第三方开发者通过这个API获取哔哩哔哩a站返回的类似JSON的数据{'name' :' Warren ',' age' :' 28'}。

这个API实际上是一个纯js文本资源,包括一个带有形式参数的函数调用语句getUserInfo(数据);用用户信息数据替换参数,最后API会返回如下文本:

GetUserInfo({ ' name ' : ' Warren ',' age ' : ' 28 ' });

同时,确保该功能存在于哔哩哔哩客户中:

脚本

函数getUserInfo(数据){

alert('您的名字是' data . name ');

提醒('你是'数据.年龄'岁。');

}

/script

然后在哔哩哔哩页面加载资源:

script src=' http://www . oicqzone.com/API . js '/script

浏览器“本能地”立即执行资源中的js语句,

参观哔哩哔哩时,会依次弹出两个对话框。这样就完成了一个JSON-P请求,真正绕过了同源的限制,实现了不同域之间的数据交互。值得一提的是,在客户端的getUserInfo函数中获取的数据实际上是JS的字面对象(理论上可以是任何对象,具体取决于服务器端传递的内容),因为API返回的文本在浏览器中被解析为JS代码,并立即执行,所以省略了JSON.parse()的步骤。

先进的

你发现了吗?以上实现和平时在本地写JS差不多!只不过调用getUserInfo()函数的代码是通过后端编写的,在客户端发送请求后返回。那么问题来了。哔哩哔哩开发人员希望使用这个API来检索除用户信息之外的更多数据,例如天气和在站A的收集。显然,一个getUserInfo()是不够的。一种更灵活的方法是,a站后端根据哔哩哔哩客户端发送的要求决定返回什么类型的数据(可执行js文本)。我们向链接调用应用编程接口添加查询参数,并告诉应用编程接口所需的数据类型:

script src=' http://www . oicqzone.com/API . js?getJSONP=getUserInfo '/脚本

或者

script src=' http://www . oicqzone.com/API . js?getJSONP=getWeather '/脚本

……

API根据查询参数getJSONP的值判断客户端需要什么样的数据,填充到相应的函数中,返回给客户端执行。这使得一个应用编程接口能够满足多个跨域请求。因此,客户端设计相应的数据处理功能是不可避免的。

异步的

原理已经掌握,可以做一些更有趣的事情,比如异步请求。聪明的读者一定猜到了——不是动态创建脚本标签或者改变现有标签的src属性值。没错!封装一个用本机JS创建脚本标记的函数:

函数getData(src){

var script=document . CreateElement(' script ');

script.src=src

document.body.appendChild(脚本);

}

随时调用它:

getData(' http://www . oicqzone.com/API . js?getJSONP=getUserInfo ');

建议将数据保存到一个新的变量中,并在数据采集成功后移除空闲脚本标签,更大限度的防止污染。

摘要

JSON-P作为一种非标准的跨域请求实现,有其固有的缺陷。虽然很聪明,但是实现起来很繁琐,很诡异。实现它的现成库是完美的,比如JQuery的jsonp。但是仍然难以弥补只接受GET请求的缺点和安全隐患。未来,JSON-P可能会被正式的跨域技术标准(如CORS)取代,但由于IE等旧浏览器的存在,JSON-P仍然是必要的,因为新标准的推进。

  • TAG:
我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航