同源政策下使用JSONP实现跨域访问

来源:互联网 发布:知乎城市冷漠 编辑:程序博客网 时间:2024/06/06 09:06

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

0 0
原创粉丝点击