Tài nguyên bên ngoài không được tải bởi AngularJs


195

Sử dụng Angular và Phonegap, tôi đang cố tải một video trên máy chủ từ xa nhưng gặp phải một vấn đề. Trong JSON của tôi, URL được nhập dưới dạng URL HTTP đơn giản.

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

Mẫu video của tôi

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

Tất cả các dữ liệu khác của tôi được tải nhưng khi tôi nhìn vào bảng điều khiển của mình, tôi gặp lỗi này:

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

Tôi đã cố gắng thêm $compileProvidervào cấu hình của mình được thiết lập nhưng nó không giải quyết được vấn đề của tôi.

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

Tôi đã thấy bài đăng này về vấn đề tên miền chéo nhưng tôi không biết làm thế nào để giải quyết vấn đề này hoặc tôi nên đi theo hướng nào. Có ý tưởng nào không? Bất kỳ trợ giúp được đánh giá cao


1
Bạn cũng có thể gửi config.xmltập tin corodva của bạn ?
Andrew Shustariov

1
Hiện tại tôi vẫn đang thử nghiệm trên trình duyệt nên tôi thậm chí chưa bắt đầu gỡ lỗi phonegap.
mhartington

Câu trả lời:


267

Đây là giải pháp duy nhất hiệu quả với tôi:

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

Sau đó, trong một 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


Điều này có thể thực hiện được nếu không có iFrame? Tôi cần nhúng video trong đó thông tin phiên xác định liệu người tiêu dùng có được phép xem video hay không. Thông tin phiên không được thực hiện thông qua iFrame.
Blake

thật tuyệt, nếu bạn có thể sử dụng iframe
Ringo

270

Một giải pháp đơn giản khác là tạo bộ lọc:

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

Sau đó chỉ định bộ lọc trong ng-src:

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

22
Chắc chắn là giải pháp thanh lịch và angulary nhất.
Sc0ttyD

1
Làm việc cho tôi và thực sự nó đẹp hơn sử dụng iframe.
Thomas Amar

1
Câu trả lời hay nhất, tinh thần góc cạnh hơn và nó hoạt động khi các giải pháp khác không vì một số lý do. Cảm ơn rất nhiều!
floribon

76

Danh sách trắng tài nguyên với $ sceDelegateProvider

Điều này được gây ra bởi một chính sách bảo mật mới được đưa ra trong Angular 1.2. Nó làm cho XSS khó hơn bằng cách ngăn chặn tin tặc quay số (nghĩa là yêu cầu URL nước ngoài, có khả năng chứa tải trọng).

Để giải quyết vấn đề này một cách chính xác, bạn cần lập danh sách trắng các tên miền bạn muốn cho phép, như thế này:

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

Ví dụ này được lấy từ tài liệu mà bạn có thể đọc ở đây:

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

Hãy chắc chắn bao gồm ngSanitize trong ứng dụng của bạn để thực hiện công việc này.

Vô hiệu hóa tính năng

Nếu bạn muốn tắt tính năng hữu ích này và bạn chắc chắn dữ liệu của mình được bảo mật, bạn chỉ cần cho phép **, như vậy:

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

2
Lưu ý: nếu resourceUrlWhitelistbằng cách nào đó không phù hợp với bạn, hãy kiểm tra xem bạn có bị gạch chéo sau tên miền không (điều này dễ xảy ra khi nối các thứ từ các biến và cả hai đều có dấu gạch chéo)
jakub.g

2
Đây là một cách sạch hơn, toàn cầu và an toàn để giải quyết vấn đề này.
DJ.

"Quay số" không phải là một thuật ngữ tuyệt vời để sử dụng cho ai đó đang cố gắng hiểu vấn đề.
Ringo

1
Cảm ơn @Ringo - Tôi đã thêm một bình luận để làm rõ.
siêu sáng

21

Có vấn đề tương tự ở đây. Tôi cần phải liên kết với các liên kết Youtube. Điều làm việc cho tôi, như một giải pháp toàn cầu , là thêm phần sau vào cấu hình của tôi:

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

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

}]);

Thêm 'cái tôi' vào đó rất quan trọng - nếu không sẽ không liên kết với bất kỳ URL nào. Từ các tài liệu góc

'Tự' - Chuỗi đặc biệt, 'tự', có thể được sử dụng để khớp với tất cả các URL của cùng một tên miền như tài liệu ứng dụng sử dụng cùng một giao thức.

Với vị trí đó, giờ đây tôi có thể liên kết trực tiếp với bất kỳ liên kết Youtube nào.

Rõ ràng bạn sẽ phải tùy chỉnh regex theo nhu cầu của bạn. Hy vọng nó giúp!


4

Giải pháp tốt nhất và dễ dàng để giải quyết vấn đề này là truyền dữ liệu của bạn từ chức năng này trong bộ điều khiển.

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

Trong trang html

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

2

Tôi gặp vấn đề tương tự khi sử dụng Videogular. Tôi đã nhận được những điều sau đây khi sử dụng ng-src:

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

Tôi đã khắc phục vấn đề bằng cách viết một chỉ thị cơ bản:

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

Các 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

Nếu bất cứ ai đang tìm kiếm một giải pháp TypeScript:

tập tin .ts (thay đổi các biến nếu có):

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

Dựa trên thông báo lỗi, vấn đề của bạn dường như có liên quan đến phép nội suy (thường là biểu thức của bạn {{}}), không liên quan đến vấn đề tên miền chéo. Về cơ bản là ng-src="{{object.src}}"hút.

ng-srcđược thiết kế với imgthẻ trong tâm trí IMO. Nó có thể không phù hợp với <source>. Xem http://docs.angularjs.org/api/ng.directive:ngSrc

Nếu bạn tuyên bố <source src="somesite.com/myvideo.mp4"; type="video/mp4"/>, nó sẽ hoạt động, phải không? (lưu ý rằng tôi loại bỏ có ng-srclợi src) Nếu không, nó phải được sửa trước.

Sau đó đảm bảo rằng {{object.src}}lợi nhuận giá trị kỳ vọng ( bên ngoài của <video>):

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

Nếu nó trả về giá trị mong đợi, câu lệnh sau sẽ hoạt động:

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

Chỉ sử dụng src và mã hóa cứng url, mọi thứ đều hoạt động như tôi muốn. Ngay khi tôi sử dụng {{object.src}} mặc dù thuộc tính src thậm chí không được thông qua. Tôi đã tiếp tục và thậm chí xóa thẻ nguồn và đặt src nội tuyến với thẻ video nhưng vẫn không có gì
mhartington

Ý tôi là bạn có chắc chắn rằng {{object.src}} trả về một giá trị không? Nó có thể trả về không xác định.
roland

{{object.src}} đang trả về một giá trị. Đã kiểm tra nó bằng cách sử dụng <p> </ p> và <a> </a>
mhartington

1
Có lẽ sẽ phải, đã tìm thấy điều này và nó trông khá tốt. cầu truyền hình.com / # . Cảm ơn sự giúp đỡ
mhartington

2
Điều này không liên quan gì đến việc ng-srcbị phá vỡ (nó không bị hỏng). Nó liên quan đến chính sách bảo mật của AngularJS: docs.angularjs.org/api/ng/service/$sce
Pauan

0

Tôi đã gặp lỗi này trong các thử nghiệm , chỉ thị templateUrlkhông đáng tin cậy, nhưng chỉ dành cho thông số kỹ thuật, vì vậy tôi đã thêm thư mục mẫu:

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

Thư mục chính của tôi là app.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.