【问题标题】:External resource not being loaded by AngularJsAngularJs 未加载外部资源
【发布时间】:2014-02-13 01:16:29
【问题描述】:

使用 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):/);

我看到了this post about cross domain issues,但我不确定如何解决这个问题或我应该往哪个方向发展。有什么想法吗?任何帮助表示赞赏

【问题讨论】:

  • 你能把你的corodva的config.xml文件也贴出来吗?
  • 现在我还在浏览器中测试所以我还没有开始我的phonegap调试。

标签: javascript angularjs cordova


【解决方案1】:

这是唯一对我有用的解决方案:

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
【解决方案2】:

我在 tests 中遇到了这个错误,指令 templateUrl 不受信任,但仅限于规范,所以我添加了模板目录:

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

我的主目录是app

【讨论】:

    【解决方案3】:

    使用 $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(['**']);
    });
    

    【讨论】:

    • 注意:如果 resourceUrlWhitelist 对您不起作用,请检查域名后是否没有双斜杠(当连接变量中的内容并且它们都有斜杠时很容易发生这种情况)
    • 这是解决此问题的更清洁、全局和安全的方法。
    • “拨出”对于试图理解问题的人来说不是一个好词。
    • 谢谢@Ringo - 我添加了一条评论来澄清。
    【解决方案4】:

    如果有人正在寻找 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>
    

    【讨论】:

      【解决方案5】:

      解决此问题的最佳且最简单的解决方案是在控制器中通过此函数传递您的数据。

      $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>
      

      【讨论】:

        【解决方案6】:

        另一个简单的解决方案是创建一个过滤器:

        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>
        

        【讨论】:

        • 绝对是最优雅和最有棱角的解决方案。
        • 为我工作,确实比使用 iframe 更好。
        • 最佳答案,更有棱角的精神,它在其他解决方案因某些原因没有的地方起作用。非常感谢!
        【解决方案7】:

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

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

        在其中添加 'self' 很重要 - 否则将无法绑定到任何 URL。来自angular docs

        'self' - 特殊字符串 'self' 可用于匹配所有 与应用文档同域的 URL,使用相同的 协议。

        有了这个,我现在可以直接绑定到任何 Youtube 链接。

        您显然必须根据自己的需要自定义正则表达式。希望对您有所帮助!

        【讨论】:

          【解决方案8】:

          我在使用 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>
          

          【讨论】:

            【解决方案9】:

            根据错误消息,您的问题似乎与 interpolation(通常是您的表达式 {{}})有关,而不是与跨域问题有关。基本上ng-src="{{object.src}}" 很烂。

            ng-src 在设计时考虑了 IMO 的 img 标签。它可能不适合&lt;source&gt;。见http://docs.angularjs.org/api/ng.directive:ngSrc

            如果您声明&lt;source src="somesite.com/myvideo.mp4"; type="video/mp4"/&gt;,它将起作用,对吗? (请注意,我删除了ng-src 以支持src)如果不是,则必须先修复它。

            然后确保{{object.src}}返回预期值(outside of &lt;video&gt;):

            <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}} 返回一个值吗?它可能会返回 undefined。
            • {{object.src}} 正在返回一个值。使用

              对其进行了测试
            • 可能不得不这样做,已经找到了,看起来还不错。 videogular.com/#。感谢您的帮助
            • 这与ng-src 被破坏无关(它没有被破坏)。它与 AngularJS 的安全策略有关:docs.angularjs.org/api/ng/service/$sce
            猜你喜欢
            • 2018-05-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-04-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多