Risorsa esterna non caricata da AngularJs


195

Utilizzando Angular e Phonegap, sto cercando di caricare un video che si trova su un server remoto ma si è verificato un problema. Nel mio JSON, l'URL viene inserito come un semplice URL HTTP.

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

Il mio modello di video

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

Tutti gli altri miei dati vengono caricati ma quando guardo la mia console, ottengo questo errore:

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

Ho provato ad aggiungere la $compileProvidermia configurazione di configurazione ma non ha risolto il mio problema.

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

Ho visto questo post su problemi tra domini ma non sono sicuro di come risolvere questo o in quale direzione dovrei andare. Qualche idea? Qualsiasi aiuto è apprezzato


1
Potresti anche pubblicare il config.xmlfile della tua corodva ?
Andrew Shustariov,

1
In questo momento sto ancora testando nel browser, quindi non ho nemmeno iniziato il mio debug di phonegap.
Mhartington,

Risposte:


267

Questa è l'unica soluzione che ha funzionato per me:

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"};
});

Quindi in un iframe:

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

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


È possibile senza un iFrame? Devo incorporare un video in cui le informazioni sulla sessione determinano se il consumatore è autorizzato o meno a vedere il video. Le informazioni sulla sessione non vengono trasferite tramite iFrame.
Blake,

bello, se puoi usare iframe
Ringo il

270

Un'altra soluzione semplice è quella di creare un filtro:

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

Quindi specificare il filtro in ng-src:

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

22
Sicuramente la soluzione più elegante e angolare.
Sc0ttyD,

1
Ha funzionato per me, ed è davvero più bello che usare un iframe.
Thomas Amar,

1
Migliore risposta, spirito più angolare e ha funzionato dove le altre soluzioni non hanno funzionato per alcuni motivi. Molte grazie!
floribon,

76

Autorizza la risorsa con $ sceDelegateProvider

Ciò è causato da una nuova politica di sicurezza messa in atto in Angular 1.2. Rende XSS più difficile impedendo a un hacker di effettuare la chiamata in uscita (ovvero fare una richiesta a un URL esterno, potenzialmente contenente un payload).

Per aggirarlo correttamente devi inserire nella whitelist i domini che vuoi consentire, in questo modo:

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**'
  ]);
});

Questo esempio è tratto dalla documentazione che puoi leggere qui:

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

Assicurati di includere ngSanitize nella tua app per farlo funzionare.

Disabilitare la funzione

Se vuoi disattivare questa utile funzione e sei sicuro che i tuoi dati siano al sicuro, puoi semplicemente consentire **, in questo modo:

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

2
Nota: se in resourceUrlWhitelistqualche modo non funziona per te, controlla se non hai una doppia barra dopo il nome di dominio (è facile che ciò accada quando si concatenano elementi dalle variabili ed entrambi hanno barre)
jakub.g

2
Questo è un modo più pulito, globale e sicuro per aggirare questo problema.
DJ.

"Chiamata in uscita" non è un ottimo termine da usare per qualcuno che cerca di capire il problema.
Ringo,

1
Grazie @Ringo - Ho aggiunto un commento per chiarire.
superluminario,

21

Ho avuto lo stesso problema qui. Avevo bisogno di legare ai link di Youtube. Ciò che ha funzionato per me, come soluzione globale , è stato aggiungere quanto segue alla mia configurazione:

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

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

}]);

L'aggiunta di 'self' è importante, altrimenti non si collegherà a nessun URL. Dai documenti angolari

'self' - La stringa speciale, 'self', può essere utilizzata per abbinare tutti gli URL dello stesso dominio del documento dell'applicazione usando lo stesso protocollo.

Con quello in atto, ora sono in grado di legare direttamente a qualsiasi link di Youtube.

Ovviamente dovrai personalizzare la regex in base alle tue esigenze. Spero che sia d'aiuto!


4

La soluzione migliore e facile per risolvere questo problema è passare i tuoi dati da questa funzione nel controller.

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

Nella pagina html

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

2

Ho riscontrato lo stesso problema con Videogular. Stavo ottenendo quanto segue quando usavo ng-src:

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

Ho risolto il problema scrivendo una direttiva di base:

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

Il codice 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

Se qualcuno è alla ricerca di una soluzione TypeScript:

File .ts (cambia le variabili ove applicabile):

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>

1

Sulla base del messaggio di errore, il problema sembra essere correlato all'interpolazione (in genere la tua espressione {{}}), non a un problema tra domini. Praticamente fa ng-src="{{object.src}}"schifo.

ng-srcè stato progettato imgpensando all'etichetta IMO. Potrebbe non essere appropriato per <source>. Vedi http://docs.angularjs.org/api/ng.directive:ngSrc

Se dichiari <source src="somesite.com/myvideo.mp4"; type="video/mp4"/>, funzionerà, giusto? (nota che rimuovo ng-srca favore di src) In caso contrario, deve essere risolto prima.

Quindi assicurarsi che {{object.src}}restituisca il valore previsto ( al di fuori di <video>):

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

Se restituisce il valore previsto, dovrebbe funzionare la seguente istruzione:

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

Usando solo SRC e hard coding dell'URL, tutto funziona come voglio. Non appena utilizzo {{object.src}} sebbene l'attributo src non venga nemmeno passato in considerazione. Sono andato avanti e ho persino rimosso il tag sorgente e ho messo l'src in linea con il tag video ma ancora niente
mhartington

Voglio dire, sei sicuro che {{object.src}} restituisce un valore? Potrebbe tornare indefinito.
roland

{{object.src}} sta restituendo un valore. Testato usando un <p> </p> e un <a> </a>
mhartington

1
Probabilmente dovrò farlo, l'ho già trovato e sembra abbastanza buono. videogular.com/# . Grazie per l'aiuto
mhartington

2
Questo non ha nulla a che fare con l' ng-srcessere rotto (non è rotto). Ha a che fare con la politica di sicurezza di AngularJS: docs.angularjs.org/api/ng/service/$sce
Pauan

0

Ho riscontrato questo errore nei test , la direttiva templateUrlnon era attendibile, ma solo per le specifiche, quindi ho aggiunto la directory dei template:

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

La mia directory principale è app.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.