web-dev-qa-db-fra.com

Ressource externe non chargée par AngularJs

En utilisant Angular et Phonegap, j'essaie de charger une vidéo sur un serveur distant, mais j'ai rencontré un problème. Dans mon JSON, l'URL est entrée en tant qu'URL HTTP simple.

"src" : "http://www.somesite.com/myvideo.mp4"

Mon modèle vidéo

 <video controls poster="img/poster.png">
       <source ng-src="{{object.src}}" type="video/mp4"/>
 </video>

Toutes mes autres données sont chargées, mais lorsque je regarde ma console, le message d'erreur suivant s'affiche:

Error: [$interpolate:interr] Can't interpolate: {{object.src}}
Error: [$sce:insecurl] Blocked loading resource from url not allowed by $sceDelegate policy.  URL

J'ai essayé d'ajouter $compileProvider dans la configuration de ma configuration, mais cela n'a pas résolu mon problème.

$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/);

J'ai vu cet article sur le problème interdomaine s mais je ne suis pas sûr de savoir comment résoudre ce problème ni dans quelle direction je devrais aller dans. Des idées? Toute aide est appréciée

193
mhartington

C'est la seule solution qui a fonctionné pour moi:

var app = angular.module('plunker', ['ngSanitize']);

app.controller('MainCtrl', function($scope, $sce) {
  $scope.trustSrc = function(src) {
    return $sce.trustAsResourceUrl(src);
  }

  $scope.movie = {src:"http://www.youtube.com/embed/Lx7ycjC8qjE", title:"Egghead.io AngularJS Binding"};
});

Puis dans un iframe:

<iframe class="youtube-player" type="text/html" width="640" height="385" ng-src="{{trustSrc(movie.src)}}" allowfullscreen frameborder="0">

http://plnkr.co/edit/tYq22VjwB10WmytQO9Pb?p=preview

266
Guy Sopher

Une autre solution simple consiste à créer un filtre:

app.filter('trusted', ['$sce', function ($sce) {
    return function(url) {
        return $sce.trustAsResourceUrl(url);
    };
}]);

Puis spécifiez le filtre dans ng-src:

<video controls poster="img/poster.png">
       <source ng-src="{{object.src | trusted}}" type="video/mp4"/>
</video>
267
David Boyd

Liste blanche de la ressource avec $ sceDelegateProvider

Ceci est dû à une nouvelle politique de sécurité mise en place dans Angular 1.2. Cela rend XSS plus difficile en empêchant un pirate informatique d’appeler (c’est-à-dire en faisant une demande à une URL étrangère, contenant potentiellement une charge utile).

Pour le contourner correctement, vous devez inclure dans la liste blanche les domaines que vous souhaitez autoriser, comme ceci:

angular.module('myApp',['ngSanitize']).config(function($sceDelegateProvider) {
  $sceDelegateProvider.resourceUrlWhitelist([
    // Allow same Origin resource loads.
    'self',
    // Allow loading from our assets domain.  Notice the difference between * and **.
    'http://srv*.assets.example.com/**'
  ]);

  // The blacklist overrides the whitelist so the open redirect here is blocked.
  $sceDelegateProvider.resourceUrlBlacklist([
    'http://myapp.example.com/clickThru**'
  ]);
});

Cet exemple provient de la documentation que vous pouvez lire ici:

https://docs.angularjs.org/api/ng/provider/$sceDelegateProvider

Assurez-vous d'inclure ngSanitize dans votre application pour que cela fonctionne.

Désactiver la fonctionnalité

Si vous souhaitez désactiver cette fonctionnalité utile et que vous êtes sûr que vos données sont sécurisées, vous pouvez simplement autoriser **, comme suit:

angular.module('app').config(function($sceDelegateProvider) {
  $sceDelegateProvider.resourceUrlWhitelist(['**']);
});
76
superluminary

Avait le même problème ici. Je devais me lier à des liens Youtube. Ce qui a fonctionné pour moi, en tant que solution globale , a été d’ajouter ce qui suit à ma configuration:

.config(['$routeProvider', '$sceDelegateProvider',
        function ($routeProvider, $sceDelegateProvider) {

    $sceDelegateProvider.resourceUrlWhitelist(['self', new RegExp('^(http[s]?):\/\/(w{3}.)?youtube\.com/.+$')]);

}]);

Ajouter 'self' est important - sinon, la liaison à une URL ne sera pas possible. De la documents angulaires

'self' - La chaîne spéciale 'self' peut être utilisée pour faire correspondre toutes les URL du même domaine que le document de l'application utilisant le même protocole.

Cela étant fait, je peux maintenant me lier directement à n’importe quel lien Youtube.

Vous devrez évidemment personnaliser la regex selon vos besoins. J'espère que ça aide!

20
zumek

La meilleure solution pour résoudre ce problème consiste à transmettre vos données à partir de cette fonction dans le contrôleur.

$scope.trustSrcurl = function(data) 
{
    return $sce.trustAsResourceUrl(data);
}

En page HTML

<iframe class="youtube-player" type="text/html" width="640" height="385" ng-src="{{trustSrcurl(video.src)}}" allowfullscreen frameborder="0"></iframe>
4

J'ai rencontré le même problème en utilisant Videogular. J'obtenais ce qui suit avec ng-src:

Error: [$interpolate:interr] Can't interpolate: {{url}}
Error: [$sce:insecurl] Blocked loading resource from url not allowed by $sceDelegate policy

J'ai résolu le problème en écrivant une directive de base:

angular.module('app').directive('dynamicUrl', function () {
return {
  restrict: 'A',
  link: function postLink(scope, element, attrs) {
    element.attr('src', scope.content.fullUrl);
  }
};
});

Le html:

 <div videogular vg-width="200" vg-height="300" vg-theme="config.theme">
    <video class='videoPlayer' controls preload='none'>
          <source dynamic-url src='' type='{{ content.mimeType }}'>
    </video>
 </div>
2
cagan

Si quelqu'un recherche une solution TypeScript:

fichier. ts (variables de changement le cas échéant)):

module App.Filters {

    export class trustedResource {

        static $inject:string[] = ['$sce'];

        static filter($sce:ng.ISCEService) {
            return (value) => {
                return $sce.trustAsResourceUrl(value)
            };
        }
    }
}
filters.filter('trustedResource', App.Filters.trusted.filter);

Html:

<video controls ng-if="HeaderVideoUrl != null">
  <source ng-src="{{HeaderVideoUrl | trustedResource}}" type="video/mp4"/>
</video>
2
GONeale

Sur la base du message d'erreur, votre problème semble être lié à interpolation (généralement votre expression {{}}), et non à un problème inter-domaines. En gros, ng-src="{{object.src}}" est nul.

ng-src a été conçu avec la balise img à l'esprit IMO. Cela pourrait ne pas être approprié pour <source>. Voir http://docs.angularjs.org/api/ng.directive:ngSrc

Si vous déclarez <source src="somesite.com/myvideo.mp4"; type="video/mp4"/>, cela fonctionnera, n'est-ce pas? (notez que je supprime ng-src en faveur de src) Sinon, il faut d'abord le corriger.

Ensuite, assurez-vous que {{object.src}} renvoie la valeur attendue ( en dehors de de <video>):

<span>{{object.src}}</span>
<video>...</video>

Si elle renvoie la valeur attendue, l'instruction suivante devrait fonctionner:

<source src="{{object.src}}"; type="video/mp4"/> //src instead of ng-src
1
roland

J'ai eu cette erreur dans tests, la directive templateUrl n'était pas fiable, mais uniquement pour la spécification, j'ai donc ajouté le répertoire du modèle:

beforeEach(angular.mock.module('app.templates'));

Mon répertoire principal est app.

0
ecoologic