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
您还可以发布corodva的config.xml文件吗?
Andrew Shustariov 2014年

1
现在,我仍在浏览器中进行测试,因此我什至没有开始进行phonegap调试。
mhartington

Answers:


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
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 2014年

1
为我工作,确实比使用iframe更好。
托马斯·阿马尔

1
最好的答案,更加棱角分明的精神,它在其他解决方案由于某些原因而无法解决的情况下起作用。非常感谢!
floribon

76

使用$ sceDelegateProvider将资源列入白名单

这是由Angular 1.2中的新安全策略引起的。通过防止黑客拨出(即,向可能包含有效负载的外部URL发出请求),XSS变得更加困难。

要正确解决此问题,您需要将要允许的域列入白名单,如下所示:

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
这是解决此问题的更清洁,全局和安全的方法。
DJ。

“拨出”不是一个试图理解该问题的人的好名词。
林戈

1
谢谢@Ringo-我添加了一条评论以澄清。
superluminary

21

在这里有同样的问题。我需要绑定到Youtube链接。作为全局解决方案,对我有用的是将以下内容添加到我的配置中:

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

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

}]);

在其中添加“自我”很重要-否则将无法绑定到任何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与视频标签内联,但还是一无所获
mhartington 2014年

我的意思是您确定{{object.src}}返回一个值吗?它可能返回未定义。
罗兰2014年

{{object.src}}返回一个值。使用<p> </ p>和<a> </a>进行了测试
mhartington 2014年

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.