JSONP浅析
DEMO : JSONP示例
为什么使用JSONP
JSONP和JSON是不一样的。JSON(JavaScript Object Notation
)是一种基于文本的数据交换方式,或者叫做数据描述格式。而JSONP(JSON with Padding
)是一种方式或者说非强制性协议。它是为了解决某个难题而产生的一种技术方式。
为什么会用到JSONP呢?
我们平时在用ajax请求服务端数据时,一般是这么写的:
$.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?
出什么问题了?被限制请求了!
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.
也就是请求来源与服务器不是同一个域名,不允许访问。这就是浏览器同源策略:
所谓"同源"指的是"三个相同":
协议相同
域名相同
端口相同
举例来说,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:
<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数据,一般是这么写的:
$data = array('name' => '52fhy', 'age' => '22');
echo json_encode($data);
exit;
这里需要改成:
$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;
}
一旦请求成功,服务端输出了:
handler({name: "52fhy", age: "22"});
这时候浏览器就要响应了,找到handler()
方法并执行,恰好,我们提前定义好了handler()
方法。
这里为什么服务端没有限制访问呢?原因是我们通过动态添加了个:
<script src="http://demo.52fhy.com/jsonp/handJsonp.php?callback=handler"></script>
它的基本思想是,网页通过添加一个<script>
元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
这种方法就是JSONP。
使用jQuery/Zepto
如果使用jQuery/Zepto,JSONP的方式将会和发送非跨域请求那样简单。
示例:
$.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里我们能接收到来自服务端的响应:
{name: "52fhy", age: "22"}
DEMO: Zepto jsonp demo
通过console控制台,可以看到请求信息:
Request URL:http://demo.52fhy.com/jsonp/handJsonp.php?_=1460899828609&callback=jsonp1
Request Method:GET
Status Code:200 OK
jQuery/Zepto为我们封装好了回调函数,一般情况下不需要我们单独去写,如果你不想在success中处理,想单独写处理函数,那么可以通过设置这2个参数来实现:
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/
JSONP浅析的更多相关文章
- json与jsonp区别浅析(json才是目的,jsonp只是手段)
一言以蔽之,json返回的是一串数据:而jsonp返回的是脚本代码(包含一个函数调用): JSON其实就是JavaScript中的一个对象,跟var obj={}在质上完全一样,只是在量上可以无限扩展 ...
- json与jsonp区别浅析(json才是目的,jsonp只是手段) (转)
一言以蔽之,json返回的是一串数据:而jsonp返回的是脚本代码(包含一个函数调用): JSON其实就是JavaScript中的一个对象,跟var obj={}在质上完全一样,只是在量上可以无限扩展 ...
- 说说JSON和JSONP,浅析JSONP解决AJAX跨域问题
说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服 ...
- 浅析跨域的方法之一 JSONP
概念: 什么叫跨域? 同源策略:它是由Netscape提出的一个著名的安全策略.现在所有支持JavaScript 的浏览器都会使用这个策略. 所谓同源是指,域名,协议,端口相同. 同源的脚本才会被执行 ...
- JSON和JSONP,浅析JSONP解决AJAX跨域问题
说到AJAX就会不可避免的面临两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不同的解决方案,比如数据可以用自定义字符串或者用XML来描述,跨域可以通过服 ...
- 浅析JSONP
什么是JSONP? JSONP是JSON with Padding的略称.它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式 ...
- 【转】json与jsonp区别浅析(json才是目的,jsonp只是手段)
一言以蔽之,json返回的是一串数据:而jsonp返回的是脚本代码(包含一个函数调用): JSON其实就是JavaScript中的一个对象,跟var obj={}在质上完全一样,只是在量上可以无限扩展 ...
- 浅析JSONP-解决Ajax跨域访问问题
浅析JSONP-解决Ajax跨域访问问题 很久没有写随笔了,总是感觉没时间,其实时间就是...废话少说,前几天,工作上有一新需求,需要前端web页面异步调用后台的Webservice方法返回信息.实现 ...
- Vue 浅析与实践
欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 作者:曾柏羲 导语 入职接到的第一个需求是实现一个关于K歌实体售卖的ERP系统,管理系统过去做过不少,这次打算换个姿势,基于时下正热但早已不新 ...
随机推荐
- Unity3D将来时:WebGL
作者:小玉链接:https://zhuanlan.zhihu.com/p/19974794来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 随着Unity5.0的发布,W ...
- java excle导出合计字段值
效果图: 代码实现: 解释: // 四个参数分别是:起始行,起始列,结束行,结束列 sheet.addMergedRegion(new Region(0, (short) (celln + 1), 0 ...
- Java 下的 JSON库性能比较:JSON.simple
JSON已经成为当前服务器与WEB应用之间数据传输的公认标准,不过正如许多我们所习以为常的事情一样,你会觉得这是理所当然的便不再深入思考了.我们很少会去想用到的这些JSON库到底有什么不同,但事实上它 ...
- shell编写mysql备份工具
如需转载,请经本人同意. 这是之前写的一个备份脚本,调用的备份工具是xtrabackup 编写思路是:每周一全备份,备份后提取lSN号,对备份文件进行压缩,其余时候在LSN的基础上进行增量备份,并对3 ...
- JavaScript-事件周期-点击替换颜色
事件周期 DOM:3个阶段 1.捕获:从最外层元素,向内层元素,逐个记录绑定的事件处理函数.默认,暂不触发任何事件 2.目标触发:优先触发目标元素绑定的事件处理函数 目标元素:实际点击的元素 3.冒泡 ...
- RedHat Enterprise Linux 7关闭防火墙方法
systemctl命令是系统服务管理器指令,它实际上将 service 和 chkconfig 这两个命令组合到一起 在之前的版本中关闭防火墙等服务的命令是 service iptables stop ...
- Web测试基础点
摘自:软件工程师成长之路 1.获取当前使用的Flash播放器版本(Flash Player Version)信息 在浏览器地址栏输入http://www.playerversion.com/,即可显示
- Android中的IntentService
首先说下,其他概念:Android中的本地服务与远程服务是什么? 本地服务:LocalService 应用程序内部------startService远程服务:RemoteService androi ...
- C++类的内存分配
今天面试被问到一个类的内存问题,有些记不清楚了.用了 C++这么年,实在是不应该. 于是上网查了一些资料,并做了实验,整理如下: 所用测试环境为64位mac air,编译器为XCode 1.最简单 c ...
- Selenium中的几种等待方式,需特别注意implicitlyWait的用法
摘:http://blog.csdn.net/pf20050904/article/details/20052485 最近在项目过程中使用selenium 判断元素是否存在的时候 遇到一个很坑爹的问题 ...