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

Posted

技术标签:

【中文标题】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 【发布时间】:2017-07-31 02:23:28 【问题描述】:

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

【问题讨论】:

见github.com/angular/angular.js/pull/15143 【参考方案1】:

$http.jsonp AngularJS V1.6 的更改

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

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

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

由于 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 Error Reference - $http:badjsonp Bad JSONP Request AngularJS $http Service API Reference - $http.jsonp

AngularJS V1.6 的进一步变化

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

    使用$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?**'
      ]);
    ]);
    

    通过 $sce.trustAsResourceUrl(url) 方法显式信任 URL。 您可以将可信对象而不是字符串作为 URL 传递给 $http 服务:

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

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

另见:

AngularJS Error Reference - $sce:insecurl Untrusted Source Blocked

AngularJS $http Service API Reference - $http.jsonp

【讨论】:

3 小时找到,你可以添加,'jsonpCallbackParam': 'callback' In param jsonpCallbackParam 的 AngularJS 默认值为 callback。仅当 API 使用的回调参数的值不是 callback 时,才需要将 jsonpCallbackParam 属性添加到配置中。【参考方案2】:

导致此问题的这两个版本之间有什么区别?

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

通过 HTTP 访问该网站的事实使情况变得更糟...

这些天更好的解决方案是使用 CORS Angular 应该没有问题,但你的 REST API 可能(取决于它的编写时间/上次更新时间)。因此,理想情况下,您将不再在客户端代码中使用 JSONP,而是自己处理转发到正确的回调。

【讨论】:

我明白你在说什么,你说得对,我可能应该做出这样的转变。我不确定如何实现那篇文章中的内容,那会是什么样子?是否完全依赖于我使用的 API? 是的,CORS 仅适用于支持它的 API。不支持 CORS 的旧 API 有时(但并非总是)支持 JSONP。如果 API 支持 CORS,最好使用标准 $http.get。 CORS 将由浏览器透明地处理。

以上是关于Angular 1.6.3 不允许 1.5.8 中允许的 JSONP 请求的主要内容,如果未能解决你的问题,请参考以下文章

ng 构建失败,在 Angular2 中出现“不允许操作,mkdir”\dir”

CoffeeScript - 不允许在 Angular 表达式中引用 DOM 节点

Angular 7:发送 post 请求给出错误 405(不允许的方法)

Angular ng-repeat 错误“不允许在转发器中重复。”

IIS 托管实体框架 CORS 的 Angular 客户端不允许响应

Angular 8 @output EventEmitter不允许发射对象