Externe Ressource wird nicht von AngularJs geladen


195

Mit Angular und Phonegap versuche ich, ein Video zu laden, das sich auf einem Remote-Server befindet, aber auf ein Problem gestoßen ist. In meinem JSON wird die URL als einfache HTTP-URL eingegeben.

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

Meine Videovorlage

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

Alle meine anderen Daten werden geladen, aber wenn ich auf meine Konsole schaue, wird folgende Fehlermeldung angezeigt:

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

Ich habe versucht, $compileProvidermeine Konfiguration einzurichten, aber mein Problem wurde dadurch nicht behoben.

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

Ich habe diesen Beitrag über domänenübergreifende Probleme gesehen , bin mir aber nicht sicher, wie ich das beheben soll oder in welche Richtung ich gehen soll. Irgendwelche Ideen? Jede Hilfe wird geschätzt


1
Könnten Sie auch die config.xmlDatei Ihrer Corodva veröffentlichen ?
Andrew Shustariov

1
Im Moment teste ich noch im Browser, daher habe ich noch nicht einmal mit dem Debuggen von Phonegap begonnen.
Mhartington

Antworten:


267

Dies ist die einzige Lösung, die für mich funktioniert hat:

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

Dann in einem 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


Ist das ohne iFrame möglich? Ich muss ein Video einbetten, in dem die Sitzungsinformationen bestimmen, ob der Verbraucher das Video sehen darf oder nicht. Die Sitzungsinformationen werden nicht über den iFrame übertragen.
Blake

schön, wenn du iframe benutzen kannst
Ringo

270

Eine andere einfache Lösung besteht darin, einen Filter zu erstellen:

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

Geben Sie dann den Filter an in ng-src:

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

22
Auf jeden Fall die eleganteste und angulärste Lösung.
Sc0ttyD

1
Hat für mich funktioniert, und in der Tat ist es schöner, als einen Iframe zu verwenden.
Thomas Amar

1
Beste Antwort, mehr Winkelgeist und es funktionierte dort, wo die anderen Lösungen aus bestimmten Gründen nicht funktionierten. Vielen Dank!
Floribon

76

Whitelist der Ressource mit $ sceDelegateProvider

Dies wird durch eine neue Sicherheitsrichtlinie verursacht, die in Angular 1.2 eingeführt wurde. Dies erschwert XSS, indem verhindert wird, dass sich ein Hacker auswählt (dh eine Anfrage an eine fremde URL stellt, die möglicherweise eine Nutzlast enthält).

Um dies richtig zu umgehen, müssen Sie die Domänen, die Sie zulassen möchten, wie folgt auf die Whitelist setzen:

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

Dieses Beispiel stammt aus der Dokumentation, die Sie hier lesen können:

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

Stellen Sie sicher, dass Sie ngSanitize in Ihre App aufnehmen, damit dies funktioniert.

Deaktivieren der Funktion

Wenn Sie diese nützliche Funktion deaktivieren möchten und sicher sind, dass Ihre Daten sicher sind, können Sie ** einfach wie folgt zulassen:

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

2
Hinweis: Wenn resourceUrlWhitelistes für Sie irgendwie nicht funktioniert, überprüfen Sie, ob Sie nach dem Domain-Namen keinen doppelten Schrägstrich haben (dies kann leicht passieren, wenn Sie
Daten

2
Dies ist ein sauberer, globaler und sicherer Weg, um dieses Problem zu umgehen.
DJ.

"Auswählen" ist kein guter Begriff für jemanden, der versucht, das Problem zu verstehen.
Ringo

1
Danke @Ringo - Ich habe einen Kommentar hinzugefügt, um dies zu verdeutlichen.
superluminary

20

Hatte hier das gleiche Problem. Ich musste mich an Youtube-Links binden. Was für mich als globale Lösung funktioniert hat, war, meiner Konfiguration Folgendes hinzuzufügen:

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

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

}]);

Das Hinzufügen von 'self' ist wichtig - andernfalls kann keine URL gebunden werden. Aus den eckigen Dokumenten

'self' - Die spezielle Zeichenfolge 'self' kann verwendet werden, um mit allen URLs derselben Domäne wie das Anwendungsdokument unter Verwendung desselben Protokolls abzugleichen.

Damit kann ich mich jetzt direkt an einen beliebigen Youtube-Link binden.

Sie müssen den regulären Ausdruck natürlich an Ihre Bedürfnisse anpassen. Ich hoffe es hilft!


4

Die beste und einfachste Lösung zur Lösung dieses Problems besteht darin, Ihre Daten von dieser Funktion in der Steuerung zu übergeben.

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

In der HTML-Seite

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

2

Ich bin mit Videogular auf dasselbe Problem gestoßen. Bei der Verwendung von ng-src wurde Folgendes angezeigt:

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

Ich habe das Problem behoben, indem ich eine grundlegende Anweisung geschrieben habe:

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

Das 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

Wenn jemand nach einer TypeScript-Lösung sucht:

.ts-Datei (ggf. Variablen ändern):

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

Basierend auf der Fehlermeldung scheint Ihr Problem mit der Interpolation (normalerweise Ihrem Ausdruck {{}}) und nicht mit einem domänenübergreifenden Problem zu tun zu haben. Grundsätzlich ng-src="{{object.src}}"saugt.

ng-srcwurde mit imgBlick auf Tag IMO entworfen. Es ist möglicherweise nicht geeignet für <source>. Siehe http://docs.angularjs.org/api/ng.directive:ngSrc

Wenn Sie erklären <source src="somesite.com/myvideo.mp4"; type="video/mp4"/>, wird es funktionieren, oder? (Beachten Sie, dass ich ng-srczugunsten von entfernesrc ) Wenn nicht, muss es zuerst behoben werden.

Stellen Sie dann sicher, dass {{object.src}}der erwartete Wert ( außerhalb von <video>) zurückgegeben wird:

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

Wenn der erwartete Wert zurückgegeben wird, sollte die folgende Anweisung funktionieren:

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

Mit nur src und harter Codierung der URL funktioniert alles wie ich will. Sobald ich {{object.src}} verwende, obwohl das src-Attribut noch nicht einmal überlegt ist. Ich ging voran und entfernte sogar das Quell-Tag und stellte den src inline mit dem Video-Tag, aber immer noch nichts
mhartington

Ich meine, sind Sie sicher, dass {{object.src}} einen Wert zurückgibt? Es könnte undefiniert zurückgegeben werden.
Roland

{{object.src}} gibt einen Wert zurück. Getestet mit einem <p> </ p> und einem <a> </a>
mhartington

1
Wahrscheinlich muss ich das schon gefunden haben und es sieht ziemlich gut aus. videogular.com/# . Vielen Dank für die Hilfe
Mhartington

2
Dies hat nichts damit zu tun ng-src, kaputt zu sein (es ist nicht kaputt). Es hat mit der Sicherheitsrichtlinie von AngularJS zu tun: docs.angularjs.org/api/ng/service/$sce
Pauan

0

Ich hatte diesen Fehler in Tests , die Direktive templateUrlwar nicht vertrauenswürdig, sondern nur für die Spezifikation, also habe ich das Vorlagenverzeichnis hinzugefügt:

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

Mein Hauptverzeichnis ist app.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.