Angular 1.6.3不允许1.5.8中允许的JSONP请求

时间:2017-03-09 22:17:51

标签: javascript angularjs jsonp angularjs-http angularjs-1.6

Angular 1.6.3不允许1.5.8中允许的请求,我收到此错误:

$sce:insecurl
Processing of a Resource from Untrusted Source Blocked

完整错误可用here

我想将我的角度版本升级到1.6.3以获得最新和最好的版本,但我依赖于此API。有没有办法让我将其标记为可信API或使用此API的其他方式?这两个版本之间有什么区别?

以下是我尝试运行的代码:

var app = angular.module('app', []);
app.controller('firstController', ['$http', function($http) {
  console.log('firstController up and running');
  var key = 'XXXXXXXXXXXXX'; // is an actual key
  var self = this;

  self.animal = {};

  self.getRandomPet = function(){
    var query = 'http://api.petfinder.com/'; // baseURL for API
    query += 'pet.getRandom'; // selecting the method we would like to return
    query += '?key=' + key; // Giving petfinder our key
    query += '&format=json'; // Telling petfinder we want our response to be JSON
    query += '&output=basic'; // Telling petfinder what data we want (more than just id)
    var request = encodeURI(query) + '&callback=JSON_CALLBACK'; // removing spaces and special characters from response as well as making jsonp work with the callback

    console.log('Request:', request);

    $http.jsonp(request).then(function(response){
      console.log(response);
      self.animal = response.data.petfinder.pet;
    });

  }

  self.getRandomPet();
}]);

整个存储库可在此处获取:https://github.com/LukeSchlangen/angular-petfinder-api

2 个答案:

答案 0 :(得分:6)

$http.jsonp对AngularJS V1.6的更改

将用于将JSONP回调传输到的查询参数 现在通过jsonpCallbackParam配置值指定服务器,而不是使用JSON_CALLBACK占位符。

  • 在JSONP请求网址中使用JSON_CALLBACK会导致错误。
  • 提供与给定名称相同的参数的任何请求 jsonpCallbackParam配置属性将导致错误。

这是为了防止来自应用程序的响应的恶意攻击,无意中允许使用不受信任的数据来生成回调参数。

由于petfinder API使用默认值"callback",只需将其从查询字符串中删除:

self.getRandomPet = function(){
    var query = 'http://api.petfinder.com/'; // baseURL for API
    query += 'pet.getRandom'; // selecting the method we would like to return
    //query += '?key=' + key; // Giving petfinder our key
    //query += '&format=json'; // Telling petfinder we want our response to be JSON
    //query += '&output=basic'; // Telling petfinder what data we want
    //var request = encodeURI(query) + '&callback=JSON_CALLBACK'; 

    //console.log('Request:', request);

    var params = { key: key,
                   format: 'json',
                   output: 'basic'
                 };                      

    //$http.jsonp(request).then(function(response){
    $http.jsonp(query, { params: params }).then(function(response){
      console.log(response);
      self.animal = response.data.petfinder.pet;
    });

  }
  

$ HTTP:

     

由于fb6634,您无法再在JSONP请求中使用JSON_CALLBACK占位符。相反,您必须提供将通过配置对象的jsonpCallbackParam属性传递回调的查询参数的名称,或通过$http.defaults.jsonpCallbackParam属性提供应用范围,默认为"callback"

     

<强>之前:

$http.jsonp('trusted/url?callback=JSON_CALLBACK');
$http.jsonp('other/trusted/url', {params: {cb: 'JSON_CALLBACK'}});
     

<强>后:

$http.jsonp('trusted/url');
$http.jsonp('other/trusted/url', {jsonpCallbackParam: 'cb'});
     

— AngularJS Developer Guide - Migrating from V1.5 to V1.6

另见:

AngularJS V1.6的进一步变化

  

由于6476af,所有JSONP请求现在都要求将URL作为资源URL进行信任。信任URL有两种方法:

     
      
  1. 使用$sceDelegateProvider.resourceUrlWhitelist()方法列入白名单。您可以在模块配置块中配置此列表:

    appModule.config(['$sceDelegateProvider', function($sceDelegateProvider) {
      $sceDelegateProvider.resourceUrlWhiteList([
          // Allow same origin resource loads.
          'self',
          // Allow JSONP calls that match this pattern
         'https://some.dataserver.com/**.jsonp?**'
      ]);
    }]);
    
  2.   
  3. 通过$sce.trustAsResourceUrl(url)方法明确信任该网址。您可以将受信任的对象而不是字符串作为URL传递给$ http服务:

    var promise = $http.jsonp($sce.trustAsResourceUrl(url));
    
  4.         

    — AngularJS Developer Guide - Migrating from V1.5 to V1.6

另见:

答案 1 :(得分:4)

  

造成这种情况的这两个版本有什么区别?

完整性检查,因为JSONP是一个非常可怕,没有好,非常糟糕的主意。至少如果你关心安全问题。您让第三方确定在您的应用程序中执行的任意代码。这是一个非常可怕的,没有好的,非常糟糕的主意。

因为通过HTTP访问网站这一事实变得更糟......

现在更好的解决方案是使用Angular应该没有问题的CORS,但是您的REST API可能(取决于它何时被编写/上次更新)。因此,理想情况下,您可以在客户端代码中使用JSONP,并自行处理转发到正确的回调。