1. 同源政策
- 1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。
- 最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页”同源”。所谓”同源”指的是”三个相同”。 即协议相同,域名相同、端口相同。
- 同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
2. JSONP
- JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。
- 它的基本思想是,网页通过添加一个
<script>
元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
2.1 JSONP原理及步骤说明
- 我们发现,Web页面上使用
<script>
元素调用js文件时不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>
)。 - 于是可以判断,当前阶段如果想通过纯web端跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理。
- 恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据。
- 这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。
- 客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了。
- 为了便于客户端使用数据,此方式逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
总结: JSONP就是本地客户端利用<script>
标签的src属性进行跨域的访问,然后取得异域服务器早已准备好的JS代码片段,由本地客户端执行的一个过程。
2.2 JSONP代码示例
本地客户端的代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript"> // 得到航班信息查询结果后的回调函数 var flightHandler = function(data){ alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。'); }; // 提供jsonp服务的URL地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码) var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; // 创建script标签,设置其属性 var script = document.createElement('script'); script.setAttribute('src',url); // 把script标签加入head,此时调用开始 document.getElementsByTagName('head')[0].appendChild(script); </script>
</head>
<body>
</body>
</html>
可以看到,本地客户端在请求的时候就将需要调用的方法名告诉了服务器,只等它返回一段调用该方法的JS代码片段即可。恰巧的是,该JS代码片段是以JSON格式传输的。
异域服务器在收到请求后,将数据转换成如下的json格式:
flightHandler({
"code": "CA1998","price": 1780,"tickets": 5 });
对,没错,上面就是json格式的返回数据。然后本地客户端得到该数据后发现是JS代码片段!执行喽!怎么执行?查找名字为flightHandler的函数啊!客户端需要的数据都在参数中,接下来看你flightHandler的函数怎么处理了。
当然,可以使用JQUERY简化使用JSONP的过程:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
<script type="text/javascript" src=jquery.min.js"></script>
<script type="text/javascript"> jQuery(document).ready(function(){ $.ajax({ type: "get",async: false,url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",dataType: "jsonp",jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback) jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据 success: function(json){ alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。'); },error: function(){ alert('fail'); } }); }); </script>
</head>
<body>
</body>
</html>
可以看到,本地客户端必须将支持JSONP的服务器接口赋给url属性,然后将datatype
设置为“jsonp”。
什么?JQUERY中找不到flightHandler的函数?我们使用的是JQUERY!他帮你进行了封装,调用的其实就是success属性对应的方法!(jsonp和jsonpCallback不是必须的)
3. 参考
http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html
http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html