最近学习了jsonp,在这里总结一下
1、什么是同源策略?跨域?
首先,jsonp是为了解决跨域而产生的一种手段。跨域是因为浏览器都满足与一种同源策略。
何谓同源:
URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。
同源策略:
浏览器的同源策略,限制了来自不同源的"document"或脚本,对当前"document"读取或设置某些属性
从一个域上加载的脚本不允许访问另外一个域的文档属性。
2、解决跨域问题的方法
(1)、Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准;不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>);
(2)、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;
(3)、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据;
(4)、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。
(5)、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。
(6)、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
3、跨域服务器
jsonp是利用<script>的跨域能力来实现,src的值为另一个域下的文件目录,即可实现跨域访问.
首先我在一个服务器上apache开启了两个端口80与800,apache的默认端口为80,只需打开800端口即可,进入/etc/httpd/conf/httpd.conf配置文件,把最后的一段注释改写成以下:
1 <VirtualHost *:800> 2 ServerAdmin [email protected]host.example.com 3 DocumentRoot /var/www/web1 4 ServerName 101.200.175.86:800 5 # ErrorLog logs/dummy-host.example.com-error_log 6 # CustomLog logs/dummy-host.example.com-access_log common 7 </VirtualHost>
重启即可,打开网页,url:800即可进入新的域,网页的根目录为www/web1/.
4、jsonp的实例
现在我们有两个域,在800端口下新建一个jsonp.html文件,在80端口下新建一个re.php文件,这里html文件将调用在其他域下的php文件,实现一个查询取数据功能
jsonp.html
1 <!doctype html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <script> 7 var localHandler = function(data){ 8 alert(data.a); //返回后台数组中a的数值 9 } 10 var url = "http://101.200.175.86/re.php?callback=localHandler"; 11 // 创建script标签,设置其属性 12 var script = document.createElement(‘script‘); 13 script.setAttribute(‘src‘, url); 14 // 把script标签加入head,此时调用开始 15 document.getElementsByTagName(‘head‘)[0].appendChild(script); 16 </script> 17 </head> 18 <body> 19 <button id="getOtherDomainThings">1111111</button> 20 21 </body> 22 </html>
url中可以添加参数
http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler
传入php文件,实现检索的作用
re.php
1 <?php 2 3 $callback = $_REQUEST[‘callback‘]; //request同时接受get与post 4 5 $output = array(‘a‘ => ‘Apple‘, ‘b‘ => ‘Banana‘); 6 7 if ($callback) { 8 header(‘Content-Type: text/javascript‘); 9 echo $callback . ‘(‘ . json_encode($output) . ‘);‘; //json_encode方法,对象转换为json 10 } else { 11 header(‘Content-Type: application/x-json‘); 12 echo json_encode($output); 13 } 14 15 ?> 16 ~
结果:
5、jquery的实现方法
jquery中把jsonp方法整合进了ajax中,但是ajax与jsonp完全不相同,ajax是通过xmlhttprequest对象来传递,jsonp是利用<script>在不同域的传递。
例子:
1 <!doctype html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 <script typpe="text/javascript" src="jquery-2.1.1.js"></script> 7 </head> 8 <body> 9 <script> 10 $(function(){ 11 $.ajax({ 12 type:"get", 13 url:"http://101.200.175.86/re.php", 14 dataType:"jsonp", //设置为jsonp格式,会实现自动的格式自动替换函数名等功能 15 jsonp:"callback", //传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名,等于callback=? 16 //jsonpCallback:"localHandler", //callback=?函数的中?的值,可以不写,jqeury会自动处理 17 success:function(data){ 18 alert(data.a); 19 } 20 }) 21 }) 22 </script> 23 </body> 24 </html>