博主博客:Stillwater的博客
知乎专栏:前端汪汪
本文为做者原创转载请注明出处:http://hiztx.top/2017/01/15/j...javascript
本文介绍了什么是跨域,为何要跨域,以及跨域的一种经常使用方法JSONP的原理。php
既然是跨域,那么确定是从一个域到另外一个域。那么首先要知道知足什么条件才是同一个域。若是两个页面拥有相同的协议,端口和域名,那么这两个页面就属于同一个源(origin),JavaScript容许这种同源页面的数据互相通讯。例如你要访问百度首页。html
https://www.baidu.com
https是协议
https协议的默认端口为443(不显示)
www.baidu.com为域名前端
注:通常端口默认为不显示,可是你能够尝试输入如下网址,发现没法访问。由于80端口默认为http协议端口。java
如今知道了什么是同一个域,那么就能够解释什么是跨域。只要协议、域名、端口有任何一个不一样,都被看成是不一样的域,之间的请求就是跨域操做。github
相信不少人都听过,同源策略。出于安全考虑,浏览器对JavaScript的不少功能进行了限制,其中一条就是,不一样域之间不予许进行数据通讯。虽然补全了安全漏洞,可是这个限制给前端开发带来了许多不便。例如:web
zhidao.baidu.com
wenku.baidu.comjson
百度知道和百度文库你们都不陌生,都是百度开发的web服务。虽然这两个都是李彦宏的,可是如今告诉他,因为你这两个域名的三级域名不同,不容许相互数据通讯。你说不行就不行?因而就有像李彦宏这样的大牛搞出一些黑科技专门用来跨域通讯。JSONP就是其中之一。segmentfault
注:
1.com为顶级域名,baidu为二级域名,zhidao/wenku为三级域名
2.跨域并不是浏览器限制了发起跨站请求,而是跨站请求能够正常发起,但返回结果被浏览器拦截了。
顾名思义:
JSONP = JSON + P
JSONP(JSON with Padding),JSON是一种轻量级的数据交换格式。而Padding在这里能够翻译为填充
。那么JSONP的意思就是,填充的JSON。是数据格式JSON的一种使用模式
,可让网页从别的网域要数据。
JSONP的核心原理就是,HTML的script标签能够加载并执行其余域JS文件。
这里区分两个概念,当咱们用浏览器打开百度知道
首页的时候,是向百度知道
服务器发送了一个Https请求,获取到百度知道
首页的index.html。若是在这个index.html里面用XMLHttpRequest对象向百度文库
服务器发送Https请求,那么就属于跨域,是不容许的。可是若是在百度知道
首页的index.html中加入一个script标签,其src属性指向百度文库
中的一个.json文件,是容许的。
为了理解这种模式的原理,先想像有一个回传JSON文件的URL,而JavaScript 程序能够用XMLHttpRequest跟这个URL要数据。假设咱们的URL是 http://server2.example.com/Re... 。假设小明的UserId 是1823,且当浏览器经过URL传小明的UserId,也就是抓取 http://server2.example.com/Re... 。获得:
{"Name": "小明", "Id": 1823, "Rank": 7 }
这个JSON数据多是依据传过去URL的查询参数动态产生的。这个时候,把 script元素的src属性设成一个回传JSON的URL是能够想像的,这也表明从HTML页面经过script元素抓取JSON是可能的。然而,一份JSON文件并非一个JavaScript程序。为了让浏览器能够在 script元素运行,从src里URL回传的必须是可运行的JavaScript。在JSONP的使用模式里,该URL回传的是由函数调用包起来的动态生成JSON,这就是JSONP的“填充(padding)”或是“前辍(prefix)”的由来。
<script type="text/javascript" src="http://server2.example.com/RetrieveUser?UserId=1823&jsonp=parseResponse"> </script>
服务器会在传给浏览器前将JSON数据填充到回调函数(parseResponse)中。浏览器获得的回应已不是单纯的数据叙述而是一个脚本。在本例中,浏览器获得的是:
{ parseResponse( { "Name": "小明", "Id": 1823, "Rank": 7 }) }
也就是说,通常状况下浏览器向服务器发送请求获得的都是数据(文本,XML,JSON),可是当采用JSONP技术时候,浏览器向跨域服务器发送请求,获得的是回调函数包住的JSON。此处JSON做为参数传入回调函数,而后再返回给浏览器。
浏览器端:
<body> <!--声明jsonpcallback回调函数,参数为json数据--> <script type="text/javascript"> function jsonpcallback(json) { console.log(json); } <!--建立一个<script>标签,设置src为一个跨域的URL,并指定回调函数为jsonpcallback--> var s = document.createElement('script'); s.src="http://localhost:8080/test.php?callback=jsonpcallback"; document.body.appendChild(s); </script> </body>
服务器端:
<?php $jsondata = '{ "name": "Stillwater", "age": 12 }'; echo $_GET['callback'].'('.$jsondata.')'; ?>
服务器返回浏览器:
jsonpcallback( { "name": "Stillwater", "age": 12 } )
在这个例子中,浏览器向服务器发出跨域请求 http://localhost:8080/test.ph... 。请求一个json数据, {"name": "Stillwater","age": 12} 。而且告诉了服务器回调函数的名字。服务器接收到请求后,就将json数据做为参数填充到回调函数中,返回给浏览器。最终返回一个填充了json数据的回调函数。
首先在客户端注册一个callback,而后把callback的名字传给服务器。
服务器先生成json数据。而后以Javascript语法的方式,生成一个function ,function名字就是传递上来的参数callback。 最后将json数据直接以入参的方式,放置到function中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的Javascript 文档,此时数据做为参数,传入到了客户端预先定义好的callback 函数里。(动态执行回调函数)
参考连接:
https://zh.wikipedia.org/wiki...
http://www.cnblogs.com/zichi/...
http://tech.jandou.com/cross-...
https://segmentfault.com/a/11...
http://wearejq.github.io/2015...