Зовнішній ресурс не завантажується AngularJs


195

Використовуючи Angular та Phonegap, я намагаюся завантажити відео, яке знаходиться на віддаленому сервері, але зіткнулося з проблемою. У моєму JSON URL вводиться як звичайна HTTP-адреса.

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

Мій шаблон відео

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

Усі інші мої дані завантажуються, але коли я дивлюся консоль, я отримую цю помилку:

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

Я намагався додати $compileProviderв налаштування конфігурації, але це не вирішило мою проблему.

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

Я бачив цю публікацію про проблему міждоменних версій , але я не впевнений, як вирішити цю проблему чи в якому напрямку я повинен піти. Будь-які ідеї? Будь-яка допомога вдячна


1
Чи можете ви також опублікувати config.xmlфайл вашого corodva ?
Андрій Шустарьов

1
Зараз я все ще тестую браузер, так що я навіть не запускав налагодження фонегапу.
mhartington

Відповіді:


267

Це єдине рішення, яке працювало для мене:

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

Тоді в кадрі:

<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


Чи можливо це без iFrame? Мені потрібно вставити відео, де інформація про сеанс визначає, чи може споживач переглядати відео чи ні. Інформація про сеанс не передається через iFrame.
Блейк

приємно, якщо ви можете використовувати iframe
Ringo

270

Ще одне просте рішення - створити фільтр:

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

Потім вкажіть фільтр у ng-src:

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

22
Однозначно найелегантніше та найпотужніше рішення.
Sc0ttyD

1
Працювало для мене, і справді це приємніше, ніж використовувати рамку.
Томас Амар

1
Найкраща відповідь, більш кутовий дух, і він працював там, де інші рішення чомусь не зробили. Дуже дякую!
floribon

76

Білий список ресурсу за допомогою $ sceDelegateProvider

Це спричинено новою політикою безпеки, введеною у Angular 1.2. Це ускладнює XSS, не дозволяючи хакеру набрати номер (тобто зробити запит на іноземну URL-адресу, що потенційно містить корисний навантаження).

Щоб правильно їх обійти, потрібно додати білий список доменів, які ви хочете дозволити, наприклад:

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

Цей приклад наведено з документації, яку ви можете прочитати тут:

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

Не забудьте включити ngSanitize у свій додаток, щоб зробити цю роботу.

Вимкнення функції

Якщо ви хочете вимкнути цю корисну функцію, і ви впевнені, що ваші дані захищені, ви можете просто дозволити **, наприклад:

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

2
Примітка: якщо resourceUrlWhitelistякимось чином не працює для вас, перевірте, чи немає у вас подвійної косої риски після доменного імені (легко це може статися при об'єднанні речей із змінних, і вони обоє мають косу
рису

2
Це більш чистий, глобальний та безпечний спосіб вирішити цю проблему.
діджей.

"Набір номера" - не чудовий термін, який можна використовувати для тих, хто намагається зрозуміти проблему.
Рінго

1
Дякую @Ringo - я додав коментар для уточнення.
суперлюмінація

21

Тут було те саме питання Мені потрібно було прив’язати посилання на Youtube. Що для мене, як глобальне рішення , було додати наступне:

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

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

}]);

Додавання "self" туди є важливим - інакше не вдасться прив’язати до будь-якої URL-адреси. З кутових док

'self' - спеціальний рядок "self" може використовуватися для відповідності всім URL-адресам того ж домену, що і документ-додаток, використовуючи той самий протокол.

Маючи це на місці, я тепер можу зв’язати безпосередньо будь-яке посилання на Youtube.

Очевидно, вам доведеться налаштувати регулярний вираз під свої потреби. Сподіваюся, це допомагає!


4

Найкраще і просте рішення для вирішення цього питання - передавати свої дані з цієї функції в контролер.

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

На html-сторінці

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

2

Я зіткнувся з тією ж проблемою, використовуючи Videogular. Під час використання ng-src я отримував таке:

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

Я вирішив проблему, написавши основну директиву:

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

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

Якщо хтось шукає рішення TypeScript:

.ts файл (зміни змінних, де це можливо):

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

Виходячи з повідомлення про помилку, ваша проблема, схоже, пов’язана з інтерполяцією (як правило, з вашим вираженням {{}}), а не з проблемою міждоменного зв’язку. В основному ng-src="{{object.src}}"смокче.

ng-srcбув розроблений з imgтегом на увазі IMO. Це може бути не підходящим для <source>. Див. Http://docs.angularjs.org/api/ng.directive:ngSrc

Якщо ви заявите <source src="somesite.com/myvideo.mp4"; type="video/mp4"/>, це буде спрацьовує, правда? (зауважте, я знімаю ng-srcна користь src) Якщо це не так, його потрібно виправити спочатку.

Потім переконайтеся , що {{object.src}}повертає очікуване значення ( за межами від <video>):

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

Якщо воно поверне очікуване значення, наступне твердження має працювати:

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

Використовуючи лише src та жорстке кодування URL-адреси, все працює так, як я хочу. Як тільки я використовую {{object.src}}, хоча атрибут src навіть не замислюється. Я пішов вперед і навіть видалив вихідний тег і поставив src в
рядок із відеотегом,

Тобто ти впевнений, що {{object.src}} повертає значення? Це може повернутися невизначено.
roland

{{object.src}} повертає значення. Випробували його, використовуючи <p> </p> та <a> </a>
mhartington

1
Напевно, доведеться це вже знайти, і це виглядає досить непогано. videogular.com/# . Дякую за допомогу
mhartington

2
Це не має нічого спільного з ng-srcтим, щоб бути зламаним (він не порушений). Це стосується політики безпеки AngularJS: docs.angularjs.org/api/ng/service/$sce
Pauan

0

У мене була помилка в тестах , директиві templateUrlне довіряли, а лише специфікації, тому я додав каталог шаблонів:

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

Головний мій каталог app.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.