超级精简:
使用JSONP主要是目的通过动态创建Script,动态拼接url,进而抓取数据,实现跨域。
确切地说,AJAX请求由于同源影响,是不允许进行跨域请求的,而Script标签src属性中的链接却可以访问跨域的js脚本,利用这一特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的JS代码,在src属性中进行调用,实现跨域。
太长不看:
首先分析问题:jsonp + 跨域,前者是方法,后者是目的。
所以我们需要对问题进行一个纵向的分析,由此产生四个问题:
问题一:什么是跨域?
跨域是指从一个“域”内,前往不同“域”获取资源。
因此在了解跨域前,我们要先了解什么是域。
众所周知,同源政策(Same origin policy)是浏览器安全的基石,而我们之前提到的“域”就是“源”。跨域问题是浏览器为了避免恶意攻击带来风险而采取的限制,若不同源,则阻止被请求的数据返回。
其中同源指的是三个相同,即:
协议相同
域名相同
端口相同
举例说明:
网址 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 :不同源(端口不同)
问题二:为什么要跨域?
我们之前都说过了,同源是为了安全,那为什么还要把脚迈出去呢?
因为随着互联网的发展,“同源政策”越来越严格,不同源下遇到的限制越来愈多。
目前,若非同源,共有三种行为受到限制:
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
虽然这些限制是必要的,但有时候真的很不方便。比如说现在的开发,流行前后端分离。
所以在实际场景中,后端开发完一部分业务代码后,提供接口给前端使用,在前后端分离的模式下,前后端的域名是不一致的,此时我们的合理需求被同源政策限制,因此需要跨域。
问题三:什么是jsonp?
了解完什么是跨域,以及为什么要跨域后。
我们再来了解它的实现方法之一:jsonp(JSON with padding)
jsonp是服务器与客户端跨域通信的常用方法,也是一种非正式的传输协议。特点是简单,兼容性强,新老浏览器都支持。
它的基本思想是:
1、网页通过添加一个<script>元素,向服务器请求JSON数据。
2、服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
jsonp该协议的一个要点:允许用户传递一个callback参数给服务端。然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
例子:
我们做一个简单的测试!
我们在http://169.254.200.238:8020/jsonp/index.html
下
向http://169.254.200.238:8080/jsonp.do
发起请求。
$.get("http://169.254.200.238:8080/jsonp.do", function (data) {
console.log(data);
});
此时浏览器抛出异常
因为两者的端口号分别为8080、8020 并不同源,从报错中也可以看出。
但是,我们换一种方式请求:
<script type="text/javascript" src="http://169.254.200.238:8080/jsonp.do">
</script>
可以看到,此时同样的请求确成功了!
由此,我们可以得出<scrpit>可以进行跨域请求,这是jsonp的基础,但是浏览器同样抛出了语句不合法的异常。
那是因为我们请求的数据会立马被浏览器当作javascript语句去执行(谁让我们用<script>去请求数据呢),但是请求到的数据格式并不符合其语法规范。
那么,如何解决这一问题呢?
如果我们返回的内容符合javascript的语法规范呢?
所以,我们把请求的数据当作一个函数的参数,并且这个函数在客户端存在的话,那么这就行得通。
例如:请求返回的数据为
callback( {"result":"success"} )
其中{"result":"success"} 是我们想要获取的数据,浏览器会立即执行callback这个函数,此时,我们已经定义好了函数名为callback这个函数:
function callback(data){
// data为返回数据
// TODO 解析数据
}
这样是不是一切都说的通了!
问题三参考来源:jsonp跨域请求详解——从繁至简
问题四:为什么jsonp可以跨域?
因为浏览器只对XHR(XMLHttpRequest)请求有同源请求限制,
而对<script>标签src属性、<img>标签src属性、<iframe>标签src属性、<link>标签ref属性没有这这种限制,利用这个“漏洞”就可以很好的解决跨域请求。
注:JSONP和JSON的关系又是什么?
JSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差别,但其实他们根本不是一回事儿。
JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。
我们拿最近比较火的谍战片来打个比方,JSON是地下党们用来书写和交换情报的“暗号”,而JSONP则是把用暗号书写的情报传递给自己同志时使用的接头方式。
一个是描述信息的格式,一个是信息传递双方约定的方法。
本篇blog学习内容参考:阮一峰老师的网络日志
网友评论