您的位置:首页 > Web前端 > AngularJS

AngularJs中的JSONP跨域访问数据传输问题

2016-09-24 16:16 309 查看

json 、jsonp

一个是JavaScript Object Notation,一个是JSON with Padding ,二个很像,但是其实不是一回事。JSON是一种数据交换格式,而JSONP是一种依靠开发人员的聪明创建出来的非官方数据交互协议。JSON是描述信息的格式,JSONP是信息传递双方约定的方法。

注意:现在浏览器是存在同源策略这个机制的,在全局层面禁止了页面加载或执行与自身来源不同的域的任何脚本。而jsonp是一种跨域绕过浏览器的安全限制,从不同的域请求数据的方法。

jsonp其实是模拟web页面上script调用js文件来实现跨域调用数据的。(不仅如此,我们还发现方式拥有“src”“href”这些属性的标签都似乎有跨域的能力,比如script、img、iframe;

如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理;JSON的纯字符数据格式可以简洁的描述复杂数据,被js原生支持,所以在web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

JSONP的原理是通过script标签发起一个GET请求来取代XHR请求。JSONP生成一个script标签并插到DOM中,然后浏览器会接管并向src属性所指向的地址发送请求。

当服务器返回请求时,响应结果会被包装成一个JavaScript函数,并由该请求所对应的回调函数调用。

AngularJS在http服务中提供了一个JSONP辅助函数。通过http服务的jsonp方法可以发送请求,如下所示:

$http .jsonp("https://api.github.com?callback=JSON_CALLBACK") .success(function(data) {

  // 数据
});


当请求被发送时,AngularJS会在DOM中生成一个如下所示< script>

标签:

  <script src="https://api.github.com?callback=angular.callbacks._0" type="text/javascript"></script>


注意,JSON_CALLBACK被替换成了一个特地为此请求生成的自定义函数。当支持JSOPN的服务器返回数据时,数据会被包装在由AngularJS生成的具名函数angular.callbacks._0中在这个例子中,GitHub服务器会返回包含在回调函数中的JSON数据,响应看起来如下所示: 

 // 简写  

  angular.callbacks._0({

    ‘meta‘: {

      ‘X-RateLimit-Limit‘: ‘60‘,

      ‘status‘: 200

    },

    ‘data‘: {

      ‘current_user_url‘: ‘https://api.github.com/user

    }

  })

当AngularJS调用指定的回调函数时会对$http的promise对象进行resolve。当我们自己开发支持JSONP的后端服务时,要确保响应的数据被包含在请求所指定的回调函数中。使用JSONP需要意识到潜在的安全风险。首先,服务器会完全开放,允许后端服务调用应用中的任何JavaScript。不受我们控制的外部站点(或者蓄意攻击者)可以随时更改脚本,使我们的整个站点变得脆弱。服务器或中间人有可能会将额外的JavaScript逻辑返回给页面,从而将用户的隐私数据暴露出来。由于请求是由script标签发送的,所以只能通过JSONP发送GET请求。并且脚本的异常也很难处理。使用JSONP一定要谨慎,同时只跟信任并可以控制的服务器进行通信。

一句话就是利用script标签绕过同源策略,获得一个类似这样的数据,jsonpcallback是页面存在的回调方法,参数就是想得到的json。

看下面案列

Jquery中jsonp的使用

myUrl = 'http://localhost:8090/api/test';

$.ajax({
type:'GET',
url:myUrl,
dataType:'jsonp',
jsonp:'callback',
jsonpCallback:'jsonpCallback',
success:function(data){
alert(data.msg);
}
});

function jsonpCallback(data){
alert(data);
}


1.jsonp只能使用get请求,解决同源问题,返回javascript代码,因为请求javascript文件是没有同源问题的。

2.当请求数据类型为jsonp时,会将callback=jsonpCallback加在url上,http://localhost:8090/api/testcallback=jsonpCallback

3.前台javascript中定义jsonpCallback函数,此函数必须定义在window下,也就是全局的函数,否则找不到。

4.后台获取请求的callback参数值jsonpCallback,返回字符串”jsonpCallback(result)”,result为返回结果。

5.请求返回的是script tag,首先会调用jsonpCallback函数,不管是否找到该函数,都会调用success函数。

6.如果没有定义jsonp和jsonpCallback,jsonp默认为”callback”,jsonpCallback会是Jquery自动生成的函数名。

angularJS中的jsonp的使用

myUrl = "http://localhost:8090/api/testcallback=JSON_CALLBACK";

$http.jsonp(myUrl).success(
  function(data){
    alert(data);
  }
);
或
$http.jsonp(myUrl,{
params:{
abc:?,
callback:'JSON_CALLBACK'
}
}).success(
  function(data){
    alert(data);
  }
);


1.angularJS中使用$http.jsonp函数

2.指定callback和回调函数名,函数名为JSON_CALLBACK时,会调用success回调函数,JSON_CALLBACK必须全为大写。

3.也可以指定其它回调函数,但必须是定义在window下的全局函数。

4.url中必须加上callback

5.当callback为JSON_CALLBACK时,只会调用success,即使window中有JSON_CALLBACK函数,也不会调用该函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  angularjs jsonp