前端跨域问题相关知识详解(原生js和jquery两种方法实现jsonp跨域)

一、同源策略javascript

同源策略(Same origin policy),它是由Netscape提出的一个著名的安全策略。同源策略是一种约定,它是浏览器最核心也最基本的安全功能,若是缺乏了同源策略,则浏览器的正常功能可能都会受到影响。能够说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现,如今全部支持JavaScript 的浏览器都会使用这个策略。php

所谓同源,就是指两个页面具备相同的协议,主机(也常说域名),端口,三个要素缺一不可。css

所谓同源策略,指的是浏览器对不一样源的脚本或者文本的访问方式进行的限制。即a.com 域名下的js没法操做b.com或是c.com域名下的对象。详细见下表:html

URL1 URL2 说明 是否容许通讯
http://www.foo.com/js/a.js http://www.foo.com/js/b.js 协议、域名、端口都相同 容许
http://www.foo.com/js/a.js http://www.foo.com:8888/js/b.js 协议、域名相同,端口不一样 不容许
https://www.foo.com/js/a.js http://www.foo.com/js/b.js 主机、域名相同,协议不一样 不容许
http://www.foo.com/js/a.js http://www.bar.com/js/b.js 协议、端口相同,域名不一样 不容许
http://www.foo.com/js/a.js http://foo.com/js/b.js 协议、端口相同,主域名相同,子域名不一样 不容许

 

URL 说明 是否容许通讯
http://www.a.com/a.js
http://www.a.com/b.js
同一域名下 容许
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不一样文件夹 容许
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不一样端口 不容许
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不一样协议 不容许
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名对应ip 不容许
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不一样 不容许
http://www.a.com/a.js
http://a.com/b.js
同一域名,不一样二级域名(同上) 不容许(cookie这种状况下也不容许访问)
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不一样域名 不容许
eg:当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪一个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。若是非同源,那么在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。
特别注意两点:
第一,若是是协议和端口形成的跨域问题“前台”是无能为力的;
第二:在跨域问题上,域仅仅是经过“URL的首部”来识别而不会去尝试判断相同的ip地址对应着两个域或两个域是否在同一个ip上。
“URL的首部”指window.location.protocol +window.location.host,也能够理解为“Domains, protocols and ports must match”。

    前端所说的跨域通常指“前台”处理跨域的办法,后台proxy这种方案牵涉到后台配置,有兴趣的能够参考yahoo的这篇文章:《JavaScript: Use a Web Proxy for Cross-Domain XMLHttpRequest Calls前端

同源策略限制了不一样源之间的交互,可咱们平时文件中引用其余域名的js文件,css文件,图片文件为什么没受到限制呢?同源策略限制的不一样源之间的交互主要针对的是js中的XMLHttpRequest等请求,下面这些状况是彻底不受同源策略限制的:java

  • 页面中的连接,重定向以及表单提交是不会受到同源策略限制的。连接就不用说了,导航网站上的连接都是连接到其余站点的。而你在域名www.foo.com下面提交一个表单到www.bar.com是彻底能够的。
  • 跨域资源嵌入是容许的,固然,浏览器限制了Javascript不能读写加载的内容。如前面提到的嵌入的<script src="..."></script>,<img>,<link>,<iframe>等。固然,若是要阻止iframe嵌入咱们网站的资源(页面或者js等),咱们能够在web服务器加上一个X-Frame-Options DENY头部来限制。nginx就能够这样设置add_header X-Frame-Options DENY;

互联网的许多网站之间图片相互盗链,A网站网页的img.src直接连接到B网站的图片地址,就是由于这个缘由:<img>的src(获取图片),<link>的href(获取css),<script>的src(获取javascript)这三个都不符合同源策略,它们能够跨域获取数据。所以,你能够直接从一些cdn上获取jQuery,而且你网站上的图片也随时可能被别人盗用。jquery

而咱们的第一种跨域方法jsonp,就是由于<script>的src不符合同源策略而来的。nginx

二、解决跨域问题-JSONP web

Asynchronous JavaScript and XML (Ajax ) 是驱动新一代 Web 站点(流行术语为 Web 2.0 站点)的关键技术。Ajax 容许在不干扰 Web 应用程序的显示和行为的状况下在后台进行数据检索。使用 XMLHttpRequest 函数获取数据,它是一种 API,容许客户端 JavaScript 经过 HTTP 链接到远程服务器。Ajax 也是许多 mashup 的驱动力,它可未来自多个地方的内容集成为单一Web 应用程序。ajax

不过,因为受到浏览器的限制,该方法不容许跨域通讯。

即:当咱们利用XMLHttpRequest对象从本地服务器获取数据时是能够的,可是它不容许跨服务器发送请求。既然XMLHttpRequest由于考虑到安全性不容许发送请求到外部服务器,只好寻找其它的办法。(见2.2。

说到AJAX首先要思考的两个问题,第一个是AJAX以何种格式来交换数据?第二个是跨域的需求如何解决?这两个问题目前都有不一样的解决方案,好比数据能够用自定义字符串或者用XML来描述,跨域能够经过服务器端代理来解决。但到目前为止最被推崇或者说首选的方案仍是用JSON来传数据,靠JSONP来跨域。

JSON(JavaScript Object Notation)和JSONP(JSON with Padding)虽然只有一个字母的差异,但其实他们根本不是一回事儿:JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明才智创造出的一种非官方跨域数据交互协议。咱们拿最近比较火的谍战片来打个比方,JSON是地下党们用来书写和交换情报的“暗号”,而JSONP则是把用暗号书写的情报传递给本身同志时使用的接头方式。看到没?一个是描述信息的格式,一个是信息传递双方约定的方法。

2.1 JSON

JSON:javaScript对象表示法(JavaScript Object Notation)

JSON is a subset of the object literal notation of JavaScript. Since JSON is a subset of JavaScript, it can be used in the language with no muss or fuss.

 JSON是一种轻量级的数据交换格式。(json.org

JSON是存储和交换文本信息的语法,相似XML。它采用键值对的方式来组织,易于人们阅读和编写,同时也易于机器解析和生成。JSON是独立于语言的,也就是说无论什么语言,均可以解析json,只须要按照json的规则来就行。

JSON语法规则:JSON可以以很是简单的方式来描述数据结构,XML能作的它都能作,所以在跨平台方面二者彻底不分伯仲。

(1)JSON只有两种数据类型描述符,大括号{}和方括号[],其他英文冒号:是映射符,英文逗号,是分隔符,英文双引号""是定义符。

(2)大括号{}用来描述一组“不一样类型的无序键值对集合”(每一个键值对能够理解为OOP的属性描述),方括号[]用来描述一组“相同类型的有序数据集合”(可对应OOP的数组)。

(3)上述两种集合中如有多个子项,则经过英文逗号,进行分隔。

(4)键值对以英文冒号:进行分隔,而且建议键名都加上英文双引号"",以便于不一样语言的解析。

(5)JSON内部经常使用数据类型有字符串、数字、布尔、日期、null 等,字符串必须用双引号引发来,其他的都不用,日期类型比较特殊,建议若是客户端没有按日期排序功能需求的话,那么把日期时间直接做为字符串传递就好,能够省去不少麻烦。

json解析的方法有两种:eval()和parse()方法。————建议尽可能使用JSON.parse方法来解析json里的字符串。

JSON和XML比较:

(1)JSON的长度和XML格式比起来很短小;

(2)JSON读写的速度更快;

(3)JSON可使用JavaScript内建的方法直接进行解析,转换成JavaScipt对象,很是方便

JSON的优势:

(1)基于纯文本,跨平台传递极其简单;

(2)Javascript原生支持,后台语言几乎所有支持;

(3)轻量级数据格式,占用字符数量极少,特别适合互联网传递;

(4)可读性强,容易编写和解析;

JSON的缺点:

(1)JSON在服务端语言的支持不像XML那么普遍,不过JSON.org上提供不少语言的库。

(2)若是你使用eval()来解析的话,会容易出现安全问题。

尽管如此,JSON的优势仍是很明显的。他是Ajax数据交互的很理想的数据格式。

2.2 JSONP

JSONP:JSON with Padding(填充式 JSON 或参数式 JSON)JSONP是一个非官方的协议,它容许在服务器端集成Script tags返回至客户端,经过javascript callback的形式实现跨域访问(这仅仅是JSONP简单的实现形式)

2.2.1 JSONP的产生

  一、一个众所周知的问题,因为同源策略,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一概不许;

  二、不过咱们又发现,Web页面上调用js文件时则不受是否跨域的影响(不只如此,咱们还发现凡是拥有”src”这个属性的标签都拥有跨域的能力,好比<script>、<img>、<iframe>);

  三、因而能够判断,当前阶段若是想经过纯web端(ActiveX控件、服务端代理、属于将来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;

  四、恰巧咱们已经知道有一种叫作JSON的纯字符数据格式能够简洁的描述复杂数据,更妙的是JSON还被js原生支持,因此在客户端几乎能够为所欲为的处理这种格式的数据;

  五、这样子解决方案就呼之欲出了,web客户端经过与调用脚本如出一辙的方式,来调用跨域服务器上动态生成的js格式文件(通常以JSON为后缀),显而易见,服务器之因此要动态生成JSON文件,目的就在于把客户端须要的数据装入进去。

  六、客户端在对JSON文件调用成功以后,也就得到了本身所需的数据,剩下的就是按照本身需求进行处理和展示了,这种获取远程数据的方式看起来很是像AJAX,但其实并不同。

  七、为了便于客户端使用数据,逐渐造成了一种非正式传输协议,人们把它称做JSONP,该协议的一个要点就是容许用户传递一个callback参数给服务端,而后服务端返回数据时会将这个callback参数做为函数名来包裹住JSON数据,这样客户端就能够随意定制本身的函数来自动处理返回数据了。

一句话总结:因为同源策略的限制,XmlHttpRequest只容许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,能够经过script标签实现跨域请求,而后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求。

如下两篇文章以浅显按部就班的方式对jsonp的概念进行了阐释,对理解其前因后果颇有帮助:

说说JSON和JSONP,也许你会豁然开朗

jsonp其实很简单【ajax跨域请求】

 2.2.2 JSONP的实现

JSONP借助了script标签节点跨域访问/获取的特性。JSONP实现跨域请求的原理简单的说,就是动态建立<script>标签,而后利用<script>的src 不受同源策略约束来跨域获取数据。

JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字通常是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。

a域名去声明一个方法,b域名去调用这个方法,经过script标签能够向不一样域名提交http请求。

1、原生js实现jsonp

 1.最简单的一种,客户端(a域名)的html文件

<!doctype html>
<html lang="en">
<head></head>
<body>
    <script type="text/javascript">
        function jsonpCallback(result) {   
            for(var i in result) {  
                console.log(i+":"+result[i]);//循环输出result的元素  
            }  
        }  
    </script>
    <script type="text/javascript" src="http://180.167.10.100/update/index.php?callback=jsonpCallback"></script>  
    <!-- 传递固定参数的方式 -->
    <!-- <script type="text/javascript" src="http://180.167.10.100/update/index.php?os=Windows&version=3.2.3.660&callback=jsonpCallback"></script> -->  
</body>
</html>

或者

<!doctype html>
<html lang="en">
<head></head>
<body>
    <script type="text/javascript">
        function jsonpCallback(result) {  
            //alert(result);  
            for(var i in result) {  
                console.log(i+":"+result[i]);//循环输出result的元素  
            }  
        }  
        var JSONP=document.createElement("script");  
        JSONP.type="text/javascript";  
        JSONP.src="http://180.167.10.100/update/index.php?callback=jsonpCallback";  
        document.getElementsByTagName("head")[0].appendChild(JSONP); 
        /*传递参数的方式*/
        /*JSONP.src="http://180.167.10.100/update/index.php?os=Windows&version=3.2.3.660&callback=jsonpCallback";*/  
    </script>
</body>
</html>    

服务端(b域名)的php代码:

<?php    
    //服务端返回JSON数据  
    //$arr=array('a'=>1,'b'=>2,'c'=>3); 
    $arr->IsLatestVersion = False;
    $arr->version = ‘3.3.2.764’;
    $arr->url = "http://172.30.28.18/update/releases/3.2.1.601/Windows/cdos-browser2_3.2.1.601.exe"; 
    $result=json_encode($arr);  
    //动态执行回调函数  
    $callback=$_GET['callback'];  
    echo $callback."($result)";  
?>

 2.在实际的项目中,咱们的jsonp通常不会直接在html文件中实现,由于向服务器获取数据的时机须要根据咱们项目的实际需求来决定,因此通常须要动态的在咱们所开发的模块或某个js文件中建立script标签以及传递相关参数(此参数也多是项目过程当中动态生成的),这时咱们能够在客户端(a域名)的js文件中以下实现:

// 获得查询结果后的回调函数
function jsonpCallback(result) {  
    for(var i in result) {  
        console.log(i+":"+result[i]);//循环输出result的元素  
    }  
}
function getVersionInfo(){
    var os = "Windows";
    var version = "3.2.3.660";
    var head = document.getElementsByTagName('head')[0];         
    var script = document.createElement('script');//建立script标签,设置其属性         
    var url = "http://180.167.10.100/update/index.php?os="+os+"&version="+version+"&callback=jsonpCallback";
    script.type = "text/javascript";                            
    script.setAttribute('src', url);//script.src= url;//提供jsonp服务的url地址
    head.appendChild(script);// 把script标签加入head,此时调用开始
}
getVersionInfo();    //具体根据实际状况在合适位置调用便可

可是此时极可能出现报错“jsonpCallback未定义”,缘由其实很简单,做为jsonp的回调函数,jsonpCallback必须是全局函数,而通常因为项目的模块化和封装咱们的函数都是局部函数,此时咱们必须将其全局化,能够将此回调函数jsonpCallback单拿出来放在html文件中,或者将其经过以下方法绑定到window对象上实现全局化:

(function(){        
    // 获得查询结果后的回调函数
    window['jsonpCallback'] = function(data){
        for(var i in result) {  
            console.log(i+":"+result[i]);//循环输出result的元素  
        }
    };
    function getVersionInfo(){
        var os = "Windows";
        var version = "3.2.3.660";
        var head = document.getElementsByTagName('head')[0];         
        var script = document.createElement('script');//建立script标签,设置其属性         
        var url = "http://180.167.10.100/update/index.php?os="+os+"&version="+version+"&callback=jsonpCallback";
        script.type = "text/javascript";                            
        script.setAttribute('src', url);//script.src= url;//提供jsonp服务的url地址
        head.appendChild(script);// 把script标签加入head,此时调用开始
    }
    getVersionInfo();//具体根据实际状况在合适位置调用便可
})();

这样jsonp的原理就很清楚了,首先在客户端注册一个callback(名字任意),而后动态建立script标签经过src引入服务器端的php文件(相似引入js文件的方式),同时将客户端注册的callback的名字传给服务器,php文件载入成功后,服务器先生成咱们须要的 json 数据,而后将其做为参数传入咱们在url参数中指定的函数,因此jsonp是须要服务器端的页面进行相应的配合的。

2、jQuery实现jsonp

jQuery自己就支持JSONP,jQuery封装的$.ajax中有一个dataType属性,将该属性设置成dataType:"jsonp",就能指定按照jsonp方式访问远程服务从而实现JSONP跨域了。

注意:虽然jQuery将JSONP封装在$.ajax中,可是其本质与$.ajax不同。若是设为dataType: 'jsonp',这个$.ajax方法就和ajax XmlHttpRequest没什么关系了,取而代之的则是JSONP协议。

注:jsonp的方式只是针对get请求方式,不支持post请求。这也是Jsonp方式的局限性

实现原理与用原生js是同样的,只不过咱们不须要手动的插入script标签以及定义回调函数,jquery在处理jsonp类型的ajax时(虽然jquery也把jsonp纳入了ajax,但其实不是一回事儿),会自动帮咱们生成回调函数并把数据取出来供success属性方法来调用。

而若是咱们想指定本身的回调函数,或者说服务上规定了固定回调函数名怎么办呢?只要以下所示添加一个jsonpCallback的选项,就能够指定咱们本身的回调方法名myCallback,远程服务接受callback参数的值就再也不是自动生成的回调名,而是myCallback

jsonp及jsonpCallback的解释:

更多参数请参考:jQuery.ajax()

客户端(a域名)的js代码实现以下:

$(document).ready(function(){
    $.ajax({
        url: "http://180.167.10.100/update/index.php",
        /*url: "http://180.167.10.100/update/index.php?os=Windows&version=3.2.3.660",*//*也能够直接在url里面传递数据*/
        type: "GET",
        dataType: "jsonp",
jsonp: "callback",//用于指示后台(php)获取数据
jsonpCallback: "myCallback",//用于添加本身的回调函数,无此项则回调函数默认为success
async:
false, data: { 'version': "3.2.3.660", 'os': "Windows", }, timeout:3000, success: function(result) { console.log(result); for(var i in result) { console.log(i+":"+result[i]);//循环输出result的元素 } }, error: function(xhr) { console.log(xhr); }, }); });

服务器端(b域名)的php代码实现以下:

<?php
header('Content-Type: text/html; charset=utf-8');
/*获取客户端的数据*/
$callback=$_GET['callback'];/*注意跟客户端指定的jsonp的值一致*/
$os = $_GET['os'];
$version = $_GET['version'];

/*对数据的操做--省略*/
/*对数据的操做--省略*/

/*将数据返回给客户端*/
$response->IsLatestVersion = False;
$response->version = '3.3.2.764';
$response->url = 'http://180.167.10.100/update/releases/3.3.2.764/Windows/cdos-browser2_update_3.3.2.764.exe'; 
$responseJSON = json_encode($response);
echo $callback."($responseJSON)";
?>

3、$.getJSON方法实现jsonp

$.getJSON()是专门为ajax获取json数据而设置的,而且支持"跨域"调用,其语法的格式为: getJSON(url,[data],[callback])     

实现原理与用原生js是同样的,一样咱们不须要手动的插入script标签以及定义回调函数,jquery会自动生成一个全局函数来替换callback=?中的问号,以后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的做用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

客户端代码实现以下:

//JQuery JSONP Support  
var url = "http://www.mydomain.com/api/suggest.php?symbol=IBM&callback=?";  
$.getJSON(url, function(result){  
    for(var i in result) {  
    console.log(i+":"+result[i]);//循环输出result的元素  
    } 
});

2.2.3 ajax和jsonp的区别

一、ajax和jsonp这两种技术在调用方式上“看起来”很像,目的也同样,都是请求一个url,而后把服务器返回的数据进行处理,所以jquery和ext等框架都把jsonp做为ajax的一种形式进行了封装;

二、但ajax和jsonp其实本质上是不一样的东西。ajax的核心是经过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。

三、因此说,其实ajax与jsonp的区别不在因而否跨域,ajax经过服务端代理同样能够实现跨域,jsonp自己也不排斥同域的数据的获取。

四、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax同样,它也不必定非要用json格式来传递数据,若是你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。

总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!

2.2.4 $.get、$.post、$getJSON、$ajax的用法跟区别

首先,$.ajax()是jquery中通用的一个ajax封装,$.get()和$.post()其实都是$.ajax()的一种,在$.ajax()中有一个type属性,专门用来指定是get请求仍是post请求的。

$.getJSON()是专门为ajax从服务器获取json数据而设置的,而且支持"跨域"调用。jQuery的getJSON()函数,只是设置了JSON参数的ajax()函数的一个简化版本。这个函数也是能够跨域使用的,相比get()、post()有必定优点。JSON是一种理想的数据传输格式,它可以很好的融合与JavaScript或其余宿主语言,而且能够被JS直接使用。使用JSON相比传统的经过 GET、POST直接发送“裸体”数据,在结构上更为合理,也更为安全。
注意:$.getJSON()数据最终仍是经过get方式发送数据出去的,这就决定了,发送的data数据量不能太多,不然形成url太长接收失败(getJSON方式是不可能有post方式递交的)。     

具体区别以下:

1.$.ajax()      
$.ajax()是jquery中通用的一个ajax封装,其语法的格式为:      
$.ajax(options)      
其中options是一个object类型,它指明了本次ajax调用的具体参数,这里我把最经常使用的几个参数附上     

$.ajax({      
    url: 'submit.aspx',      
    datatype: "json",      
    type: 'post',      
    success: function (e) {      
        //成功后回调      
        alert("回调函数成功了");      
     },      
    error: function(e){      
        //失败后回调      
        alert("服务器请求失败");      
    },      
    beforeSend: function(){      
        //发送请求前调用,能够放一些"正在加载"之类额话      
        alert("正在加载");           
    }
})

2.$.get      
    $.get()方法使用GET方式来进行异步请求,它的语法结构为:      
    $.get( url [, data] [, callback] )      
    解释一下这个函数的各个参数:      
    url:string类型,ajax请求的地址。      
    data:可选参数,object类型,发送至服务器的key/value数据会做为QueryString附加到请求URL中。      
    callback:可选参数,function类型,当ajax返回成功时自动调用该函数。

$.get("submit.php",{id:'123',name:'小王',},function(data,state){              
    //这里显示从服务器返回的数据            
    alert(data);          
    //这里显示返回的状态                
    if(state == 'ok'){      
        alert("返回数据成功");      
    }else{      
        alert("返回数据失败");      
    }      
});

3.$.post()      
    $.post()方法使用POST方式来进行异步请求,它的语法结构为:      
    $.post(url,[data],[callback],[type])      
    这个方法和$.get()用法差很少,惟独多了一个type参数,那么这里就只介绍type参数吧,其余的参考上面$.get()的。      
    type:type为请求的数据类型,能够是html,xml,json等类型,若是咱们设置这个参数为:json,那么返回的格式则是json格式的,若是没有设置,就和$.get()返回的格式同样,都是字符串的。

$.post("submit.php",{id:'123',name:'小明',},function(data,state){              
    //这里显示从服务器返回的数据             
    alert(data);        
    //这里显示返回的状态            
    if(state == 'ok'){      
        alert("返回数据成功");      
    }else{      
        alert("返回数据失败");      
    },
"json");

4.$.getJSON()      
    $.getJSON()是专门为ajax获取json数据而设置的,而且支持"跨域"调用,其语法的格式为:      
    getJSON(url,[data],[callback])      
    url:string类型, 发送请求地址      
    data :可选参数, 待发送 Key/value 参数 ,同get,post类型的data      
    callback :可选参数,载入成功时回调函数,同get,post类型的callback

2.2.4 JSONP的优缺点

JSONP使用起来方便,是目前比较流行的跨域方式,它的优缺点以下:

JSONP的优势

(1)它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制,JSONP能够跨越同源策略;
(2)它的兼容性更好,在更加古老的浏览器中均可以运行,不须要XMLHttpRequest或ActiveX的支持
(3)在请求完毕后能够经过调用callback的方式回传结果。将回调方法的权限给了调用方。这个就至关于将controller层和view层终于分开了。我提供的jsonp服务只提供纯服务的数据,至于提供服务以 后的页面渲染和后续view操做都由调用者来本身定义就行了。若是有两个页面须要渲染同一份数据,大家只须要有不一样的渲染逻辑就能够了,逻辑均可以使用同 一个jsonp服务。

JSONP的缺点:适用范围过小(只能GET), 有安全风险(返回的代码会直接执行)
(1)它只支持GET请求而不支持POST等其它类型的HTTP请求
(2)它只支持跨域HTTP请求这种状况,不能解决不一样域的两个页面之间如何进行JavaScript调用的问题。
(3)jsonp在调用失败的时候不会返回各类HTTP状态码,要肯定 JSONP 请求是否失败并不容易。虽然 HTML5 给<script>元素新增了一个 onerror事件处理程序,但目前尚未获得任何浏览器支持。为此,开发人员不得不使用计时器检测指定时间内是否接收到了响应。
(4)存在安全风险。由于JSONP 是从其余域(服务端)中加载代码并直接执行,若是其余域不安全,极可能会在响应中夹带一些恶意代码,因而全部调用这个 jsonp的网站都会存在漏洞,没法把危险控制在一个域名下,而此时除了彻底放弃 JSONP 调用以外,没有办法追究。所以在使用不是你本身运维的 Web 服务时,必定得保证它安全可靠。

 三、解决跨域问题-CORS/XHR2

3.1 概念

为了改善网络应用程序,开发人员要求浏览器供应商容许跨域请求。

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-Origin Resource Sharing),它容许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

跨域请求主要用于:

  • 调用XMLHttpRequest或fetchAPI经过跨站点方式访问资源
  • 网络字体,例如Bootstrap(经过CSS使用@font-face 跨域调用字体)
  • 经过canvas标签,绘制图表和视频。

HTML5提供的XMLHttpRequest Level2已经实现了跨域访问以及其余的一些新功能,CORS须要浏览器和服务器同时支持。目前,全部浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通讯过程,都是浏览器自动完成,不须要用户参与。对于开发者来讲,CORS通讯与同源的AJAX通讯没有差异,代码彻底同样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感受。所以,实现CORS通讯的关键是服务器。只要服务器实现了CORS接口,就能够跨源通讯。

3.2 实现

CORS背后的基本思想是使用自定义的HTTP头部容许浏览器和服务器相互了解对方,从而决定请求或响应成功与否.

Access-Control-Allow-Origin:指定受权访问的域
Access-Control-Allow-Methods:受权请求的方法(GET, POST, PUT, DELETE,OPTIONS等)

如在服务器端添加以下代码便可:
header('Access-Control-Allow-Origin:*');//设置能够访问的域,星号表明全部域均可以访问
header('Access-Control-Allow-Methods:POST,GET');

配合XHR2的IE10如下跨域:
在代码中js加上一句jQuery.support.cors =true;或者$.support.cors =true; 
而后:设置IE浏览器->Internet选项->安全->自定义级别->其余选项下面的->经过源数据:选择“启用”或者“提示”

详细可参考:

跨域资源共享 CORS 详解

利用CORS实现跨域请求

CORS——跨域请求那些事儿

CORS 跨域 实现思路及相关解决方案

3.3 CORS 对比 JSONP

都能解决 Ajax直接请求普通文件存在跨域无权限访问的问题

(1)JSONP只能实现GET请求,而CORS支持全部类型的HTTP请求

(2)使用CORS,开发者可使用普通的XMLHttpRequest发起请求和得到数据,比起JSONP有更好的错误处理

(3)JSONP主要被老的浏览器支持,它们每每不支持CORS,而绝大多数现代浏览器都已经支持了CORS!

四、解决跨域问题-代理

经过在同域名的web服务器端建立一个代理,用本地服务器的后台调用其余域的后台服务,而后把相应结果返回给前端,这样前端调用同域名服务器的服务和其余域的服务同样了。(由后台实现,了解

五、其余跨域方法

参考:

JavaScript跨域总结与解决办法

js中几种实用的跨域方法原理详解

相关文章
相关标签/搜索