El recurso externo no está siendo cargado por AngularJs

195

Usando Angular y Phonegap, estoy tratando de cargar un video que está en un servidor remoto pero encontré un problema. En mi JSON, la URL se ingresa como una URL HTTP simple.

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

Mi plantilla de video

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

Todos mis otros datos se cargan, pero cuando miro mi consola, aparece este error:

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

Intenté agregar $compileProvidermi configuración de configuración pero no resolvió mi problema.

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

Vi esta publicación sobre problemas entre dominios, pero no estoy seguro de cómo resolver esto o en qué dirección debo ir. ¿Alguna idea? Cualquier ayuda es apreciada

mhartington
fuente
1
¿Podrías también publicar el config.xmlarchivo de tu corodva ?
Andrew Shustariov
1
En este momento todavía estoy probando en el navegador, así que ni siquiera he comenzado a depurar mi teléfono.
mhartington

Respuestas:

267

Esta es la única solución que funcionó para mí:

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

Luego en 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

Guy Sopher
fuente
¿Es esto posible sin un iFrame? Necesito insertar un video donde la información de la sesión determina si el consumidor puede o no ver el video. La información de la sesión no se transmite a través del iFrame.
Blake
bueno, si puedes usar iframe
Ringo
270

Otra solución simple es crear un filtro:

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

Luego especifique el filtro en ng-src:

<video controls poster="img/poster.png">
       <source ng-src="{{object.src | trusted}}" type="video/mp4"/>
</video>
David Boyd
fuente
22
Definitivamente la solución más elegante y angular.
Sc0ttyD
1
Funcionó para mí, y de hecho es mejor que usar un iframe.
Thomas Amar
1
La mejor respuesta, un espíritu más angular y funcionó donde las otras soluciones no lo hicieron por algunas razones. ¡Muchas gracias!
floribon
76

Incluya en la lista blanca el recurso con $ sceDelegateProvider

Esto se debe a una nueva política de seguridad implementada en Angular 1.2. Hace que XSS sea más difícil al evitar que un pirata informático marque (es decir, realizar una solicitud a una URL extranjera, que posiblemente contenga una carga útil).

Para evitarlo correctamente, debe incluir en la lista blanca los dominios que desea permitir, de esta manera:

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

Este ejemplo se extrae de la documentación que puede leer aquí:

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

Asegúrese de incluir ngSanitize en su aplicación para que esto funcione.

Deshabilitar la función

Si desea desactivar esta útil función, y está seguro de que sus datos están seguros, simplemente puede permitir **, así:

angular.module('app').config(function($sceDelegateProvider) {
  $sceDelegateProvider.resourceUrlWhitelist(['**']);
});
superluminario
fuente
2
Nota: si de resourceUrlWhitelistalguna manera no funciona para usted, verifique si no tiene una barra doble después del nombre de dominio (es fácil que esto suceda al concatenar cosas de variables y ambas tienen barras)
jakub.g
2
Esta es una forma más limpia, global y segura de solucionar este problema.
DJ
"Marcar" no es un término excelente para alguien que intenta comprender el problema.
Ringo
1
Gracias @Ringo: he agregado un comentario para aclarar.
superluminary el
21

Tuve el mismo problema aquí. Necesitaba unirme a los enlaces de Youtube. Lo que funcionó para mí, como solución global , fue agregar lo siguiente a mi configuración:

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

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

}]);

Agregar 'self' allí es importante; de ​​lo contrario, no se vinculará a ninguna URL. De los documentos angulares

'self': la cadena especial, 'self', se puede utilizar para hacer coincidir todas las URL del mismo dominio que el documento de la aplicación con el mismo protocolo.

Con eso en su lugar, ahora puedo vincular directamente a cualquier enlace de Youtube.

Obviamente, tendrá que personalizar la expresión regular según sus necesidades. ¡Espero eso ayude!

zumek
fuente
4

La mejor y más fácil solución para resolver este problema es pasar sus datos de esta función en el controlador.

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

En la página html

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

Me encontré con el mismo problema usando Videogular. Recibía lo siguiente cuando usaba ng-src:

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

Solucioné el problema escribiendo una directiva básica:

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

El 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>
cagan
fuente
2

Si alguien está buscando una solución TypeScript:

archivo .ts (cambie las variables cuando corresponda):

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>
GONeale
fuente
1

Según el mensaje de error, su problema parece estar relacionado con la interpolación (generalmente su expresión {{}}), no con un problema de dominio cruzado. Básicamente ng-src="{{object.src}}"apesta.

ng-srcfue diseñado con la imgetiqueta en mente IMO. Puede que no sea apropiado para <source>. Ver http://docs.angularjs.org/api/ng.directive:ngSrc

Si declaras <source src="somesite.com/myvideo.mp4"; type="video/mp4"/>, funcionará, ¿verdad? (tenga en cuenta que elimino ng-srca favor desrc ) Si no, debe solucionarse primero.

Luego, asegúrese de que {{object.src}}devuelve el valor esperado ( fuera de <video>):

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

Si devuelve el valor esperado, la siguiente instrucción debería funcionar:

<source src="{{object.src}}"; type="video/mp4"/> //src instead of ng-src
Roland
fuente
Usando solo src y codificando la url, todo funciona como quiero. Tan pronto como uso {{object.src}}, aunque el atributo src ni siquiera se pasa por alto. Seguí adelante e incluso eliminé la etiqueta de origen y puse el src en línea con la etiqueta de video pero todavía nada
mhartington
Quiero decir, ¿estás seguro de que {{object.src}} devuelve un valor? Puede volver indefinido.
roland
{{object.src}} está devolviendo un valor. Lo probé usando un <p> </p> y un <a> </a>
mhartington
1
Probablemente va a tener que hacerlo, ya encontré esto y se ve bastante bien. videogular.com/# . Gracias por la ayuda
mhartington
2
Esto no tiene nada que ver con ng-srcestar roto (no está roto). Tiene que ver con la política de seguridad de AngularJS: docs.angularjs.org/api/ng/service/$sce
Pauan
0

Tuve este error en las pruebas , la directiva templateUrlno era confiable, pero solo para la especificación, así que agregué el directorio de plantilla:

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

Mi directorio principal es app.

ecoologico
fuente