Внешний ресурс не загружается AngularJs


195

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

"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
Прямо сейчас я все еще тестирую в браузере, поэтому я даже не начал отладку телефонного пробела.
Мхартингтон

Ответы:


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:

<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
Ринго

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
Работал на меня, и это действительно лучше, чем использование iframe.
Томас Амар

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то не работает для вас, проверьте, не у вас ли двойная косая черта после доменного имени (это легко сделать при объединении вещей из переменных, и у них обеих есть косая черта)
jakub.g

2
Это более чистый, глобальный и безопасный способ обойти эту проблему.
DJ.

«Вызов» не является хорошим термином для тех, кто пытается понять проблему.
Ринго

1
Спасибо @Ringo - я добавил комментарий, чтобы уточнить.
superluminary

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 в строку с тегом video, но все еще ничего
mhartington

Я имею в виду, вы уверены, что {{object.src}} возвращает значение? Это может вернуть неопределенное.
Роланд

{{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.