您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

JSONP浅析

时间:2019-08-30 09:58:01  来源:  作者:

JSONP和JSON是不一样的。JSON(JAVAScript Object Notation)是一种基于文本的数据交换方式,或者叫做数据描述格式。而JSONP(JSON with Padding)是一种方式或者说非强制性协议。它是为了解决某个难题而产生的一种技术方式。

为什么会用到JSONP呢?

我们平时在用ajax请求服务端数据时,一般是这么写的:

Copy
$.ajax({
 type: "get",
 url: "getData.php",
 dataType: "json",
 success: function (data, textStatus, jqXHR) {
 console.log(data);
 },
 error: function (XMLHttpRequest, textStatus, errorThrown) {
 alert('fail');
 }
});

这是一段很普通的基于jQuery的AJAX请求,不会有什么问题。注意到:url里是getData.php,说明这个文件url是基于当前服务器的,例如可能是localhost,也就是前端发出的请求来源是localhost,后端肯定也是localhost。他们俩是在同一个域名下。当然,平时我们也不会特别注意。

这时候,假如这个url变成其它服务器上的地址,例如:'http://apis.juhe.cn/mobile/get?phone=13429667914&key=',我们再把请求发送出去,会发现出问题了。大家可以手动写个示例看看。

DEMO: 为什么使用jsonp?

出什么问题了?被限制请求了!

Copy
XMLHttpRequest cannot load http://apis.juhe.cn/mobile/get?phone=13429667914&key=. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://demo.52fhy.com' is therefore not allowed access.

也就是请求来源与服务器不是同一个域名,不允许访问。这就是浏览器同源策略:

Copy
所谓"同源"指的是"三个相同":
协议相同
域名相同
端口相同
举例来说,http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。它的同源情况如下。
http://www.example.com/dir2/other.html:同源
http://example.com/dir/other.html:不同源(域名不同)
http://v2.www.example.com/dir/other.html:不同源(域名不同)
http://www.example.com:81/dir/other.html:不同源(端口不同)

同源政策规定,AJAX请求只能发给同源的网址,否则就报错。

那么,这时候该怎么办呢?我就是想通过js请求对方服务器上的资源!

除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制。

  • JSONP
  • WebSocket
  • CORS

本文只对JSONP作介绍。

如何使用JSONP

首先前端这边代码得改改,假设先不用jQuery:

Copy
<script type="text/JavaScript">
//跨域发送HTTP请求,从服务端获取数据,callback指定回调函数名称
var url = 'http://demo.52fhy.com/jsonp/handJsonp.php?callback=handler';
function getHello() {
 var script = document.createElement('script');
 script.setAttribute('src', url);
 document.querySelector("head").AppendChild(script);
}
// 处理函数
function handler(data) {
 console.log(data);
 // our code here...
}
</script>
<input type="button" value="发送跨域HTTP请求,获取数据" onclick="getHello()" />

后端服务器也要改改。

例如,在PHP语言中,后端服务器在API里返回JSON数据,一般是这么写的:

Copy
$data = array('name' => '52fhy', 'age' => '22');
echo json_encode($data);
exit;

这里需要改成:

Copy
$data = array('name' => '52fhy', 'age' => '22');
handJsonp($data);
//处理jsonp
function handJsonp($data){
 $callback = $_GET['callback'] ? : 'callback'; //默认使用callback
 echo sprintf("%s(%s)", $callback, json_encode($data));
 exit;
}

一旦请求成功,服务端输出了:

Copy
handler({name: "52fhy", age: "22"});

这时候浏览器就要响应了,找到handler()方法并执行,恰好,我们提前定义好了handler()方法。

这里为什么服务端没有限制访问呢?原因是我们通过动态添加了个:

Copy
<script src="http://demo.52fhy.com/jsonp/handJsonp.php?callback=handler"></script>

它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

这种方法就是JSONP。

使用jQuery/Zepto

如果使用jQuery/Zepto,JSONP的方式将会和发送非跨域请求那样简单。

示例:

Copy
$.ajax({
 type: "get",
 async: false,
 url: "http://demo.52fhy.com/jsonp/handJsonp.php",
 dataType: "jsonp",
 success: function (data, textStatus, jqXHR) {
 console.log(data);
 },
 error: function (XMLHttpRequest, textStatus, errorThrown) {
 alert('fail');
 console.log(XMLHttpRequest, textStatus, errorThrown);
 }
});

只需要将dataType设置成jsonp就可以进行跨域请求了。在success里我们能接收到来自服务端的响应:

Copy
{name: "52fhy", age: "22"}

DEMO: Zepto jsonp demo

通过console控制台,可以看到请求信息:

Copy
Request URL:http://demo.52fhy.com/jsonp/handJsonp.php?_=1460899828609&callback=jsonp1
Request Method:GET
Status Code:200 OK

jQuery/Zepto为我们封装好了回调函数,一般情况下不需要我们单独去写,如果你不想在success中处理,想单独写处理函数,那么可以通过设置这2个参数来实现:

Copy
jsonp: "callback",//传递给服务端的回调函数名称参数,如果不设置此项,则默认是"callback"
jsonpCallback: "handler",//传递给服务端的回调函数名称,如果不设置此项,jQuery默认是形如"jQuery18308539637457579374_1460898291266"的由jQuery自动生成的函数名称,Zepto默认是`jsonp1`

如果是zepto,可以在success回调里面使用console.log(jsonp1),发现jsonp1()方法是存在的。

需要注意的是:

1.JSONP虽然看起来很像一般的ajax请求,但其原理不同,JSONP是通过<script>标签的动态加载来实现的跨域请求,而一般的ajax请求是通过XMLHttpRequest对象进行;

2.JSONP不是一种标准协议,其安全性和稳定性都不如 W3C 推荐的 CORS;

3.JSONP不支持POST请求,即使把请求类型设置为post,其本质上仍然是一个get请求。

参考

1、浏览器同源政策及其规避方法 - 阮一峰的网络日志

http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html

2、跨域资源共享 CORS 详解 - 阮一峰的网络日志

http://www.ruanyifeng.com/blog/2016/04/cors.html

3、说说JSON和JSONP,也许你会豁然开朗_知识库_博客园

http://kb.cnblogs.com/page/139725/

4、跨域解决方案二:使用JSONP实现跨域 - choon - 博客园

http://www.cnblogs.com/choon/p/5393682.html

5、JSON-P: Safer cross-domain Ajax with JSON-P/JSONP

http://json-p.org/

本文首发于公众号"飞鸿影的博客(fhyblog)",欢迎关注。博客地址:https://52fhy.cnblogs.com

(本文完)



Tags:JSONP   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
声明由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。雷神众测拥有对此文章的修改和解释...【详细内容】
2020-08-31  Tags: JSONP  点击:(223)  评论:(0)  加入收藏
那么我们今天就来了解一下cors跨域和jsonp劫持漏洞同源策略为什么还要讲一遍同源策略,我们之前写xss的时候有讲到过,不了解的同学可以看看我们的那篇xss文章,那么该策略是浏览...【详细内容】
2020-02-16  Tags: JSONP  点击:(421)  评论:(0)  加入收藏
JSONP和JSON是不一样的。JSON(JavaScript Object Notation)是一种基于文本的数据交换方式,或者叫做数据描述格式。而JSONP(JSON with Padding)是一种方式或者说非强制性协议...【详细内容】
2019-08-30  Tags: JSONP  点击:(203)  评论:(0)  加入收藏
从事前端开发的小伙伴肯定都用过jquery的ajax请求,但如果需要跨域请求,就需要用到jsonp,因为默认的ajax跨域请求会被浏览器拦截,拦截原因是因为支持Javascript的浏览器都会使用...【详细内容】
2019-06-19  Tags: JSONP  点击:(399)  评论:(0)  加入收藏
▌简易百科推荐
本文分为三个等级自顶向下地分析了glibc中内存分配与回收的过程。本文不过度关注细节,因此只是分别从arena层次、bin层次、chunk层次进行图解,而不涉及有关指针的具体操作。前...【详细内容】
2021-12-28  linux技术栈    Tags:glibc   点击:(3)  评论:(0)  加入收藏
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(2)  评论:(0)  加入收藏
程序是如何被执行的&emsp;&emsp;程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(10)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(20)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(25)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(25)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条