AngularJs ไม่ได้โหลดทรัพยากรภายนอก


195

ใช้ Angular และ Phonegap ฉันพยายามโหลดวิดีโอที่อยู่บนเซิร์ฟเวอร์ระยะไกล แต่เจอปัญหา ใน JSON ของฉัน URL ถูกป้อนเป็น URL HTTP ธรรมดา

"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 ของคุณหรือไม่
Andrew Shustariov

1
ตอนนี้ฉันยังทำการทดสอบในเบราว์เซอร์ดังนั้นฉันยังไม่ได้เริ่มการดีบักโทรศัพท์ของฉัน
mhartington

คำตอบ:


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
แน่นอนทางออกที่หรูหราที่สุดและ angulary
Sc0ttyD

1
ได้ผลสำหรับฉันและแน่นอนว่ามันดีกว่าการใช้ iframe
โทมัสอามาร์

1
คำตอบที่ดีที่สุดวิญญาณที่มีมุมมากขึ้นและใช้งานได้ดีกว่าที่โซลูชันอื่น ๆ ไม่ได้ด้วยเหตุผลบางประการ ขอบคุณมาก!
floribon

76

รายการทรัพยากรที่อนุญาตด้วย $ sceDelegateProvider

สิ่งนี้เกิดจากนโยบายความปลอดภัยใหม่ที่วางไว้ใน Angular 1.2 มันทำให้ XSS หนักขึ้นโดยการป้องกันไม่ให้แฮ็กเกอร์โทรออก (เช่นการขอ URL ต่างประเทศซึ่งอาจมี payload)

ในการรับมันอย่างถูกต้องคุณจะต้องอนุญาตโดเมนที่คุณต้องการอนุญาตเช่นนี้:

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
นี่เป็นวิธีที่สะอาดกว่าทั่วโลกและปลอดภัยในการแก้ไขปัญหานี้
ดีเจ

"การโทรออก" ไม่ใช่คำศัพท์ที่ยอดเยี่ยมสำหรับผู้ที่พยายามเข้าใจปัญหา
ริงโก้

1
ขอบคุณ @Ringo - ฉันได้เพิ่มความคิดเห็นเพื่อชี้แจง
แสงสว่าง

21

มีปัญหาเดียวกันที่นี่ ฉันต้องผูกกับลิงก์ Youtube สิ่งที่ใช้ได้ผลสำหรับฉันในฐานะโซลูชันระดับโลกคือการเพิ่มสิ่งต่อไปนี้ในการกำหนดค่าของฉัน:

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

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

}]);

การเพิ่ม'ตนเอง'ในนั้นมีความสำคัญมิฉะนั้นจะไม่สามารถผูกกับ URL ใด ๆ ได้ จากเอกสารเชิงมุม

'self' - สตริงพิเศษ 'self' สามารถใช้จับคู่กับ URL ทั้งหมดของโดเมนเดียวกันกับเอกสารแอปพลิเคชันโดยใช้โปรโตคอลเดียวกัน

ตอนนี้ฉันสามารถเชื่อมโยงกับลิงก์ Youtube ได้โดยตรง

คุณจะต้องปรับแต่ง regex ให้ตรงกับความต้องการของคุณ หวังว่ามันจะช่วย!


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

ฉันหมายความว่าคุณแน่ใจหรือว่า {{object.src}} คืนค่า? มันอาจกลับมาไม่ได้กำหนด
roland

{{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ไดเรกทอรีหลักของฉันคือ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.