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

Angular 1.6.3 is not allowing a JSONP request that was allowed in 1.5.8

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

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

完整错误可用here

我想将我的 angular 版本升级到 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

What is the difference between these two versions that is causing this?

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

由于网站是通过 HTTP 访问的,所以情况变得更糟...

最近更好的解决方案是使用 CORS,Angular 应该没有问题,但是您的 REST API 可能(取决于它是什么时候 written/last 更新)。因此,理想情况下,您将远离在客户端代码中使用 JSONP,自己处理转发到适当的回调。

$http.jsonp AngularJS V1.6

的更改

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

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

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

由于宠物查找器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:

Due to fb6634, you can no longer use the JSON_CALLBACK placeholder in your JSONP requests. Instead you must provide the name of the query parameter that will pass the callback via the jsonpCallbackParam property of the config object, or app-wide via the $http.defaults.jsonpCallbackParam property, which is "callback" by default.

Before:

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

After:

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

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

另请参阅:


AngularJS V1.6

中的进一步更改

Due to 6476af, all JSONP requests now require the URL to be trusted as a resource URL. There are two approaches to trust a URL:

  1. Whitelisting with the $sceDelegateProvider.resourceUrlWhitelist() method. You configure this list in a module configuration block:

    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. Explicitly trusting the URL via the $sce.trustAsResourceUrl(url) method. You can pass a trusted object instead of a string as a URL to the $http service:

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

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

另请参阅: