2013-09-27 6 views
7

Ich arbeite auf einer CMS-gesteuerten Website mit Angular (1.2 RC2) auf der Client-Seite. Da der Inhalt von einem CMS stammt, muss ich leider HTML in JSON Strings empfangen. Der größte Teil des HTML-Codes wird injiziert und gerendert, aber Bild-Tags haben ihre src entfernt. Von dem, was ich gelesen habe, sollte der src mit "unsafe:" vorangestellt sein, nicht vollständig entfernt, wenn dies ein XSS-Sicherheitsproblem in Angular war .. aber ich könnte mich irren.Angular 1.2: ng-bind-html entfernt src Attribut auf img

Ich war schon eine Weile an diesem Problem und habe das Gefühl, ich habe alles versucht, von plausibel bis geradezu dumm. Whitelisting meine CMS URL, Whitelisting alles, Deaktivieren $ sce, zwingen HTML durch $ sce.trustAsHtml() und gut ... Bisher kein Glück. Da die Seite CMS-gesteuert ist, bin ich leider nicht in der Lage, einen Plünderer/Geiger zu erschaffen, aber ich hoffe, dass eine nette Seele versuchen wird, trotzdem zu helfen.

aktualisieren: Vergessen zu erwähnen, dass ich auch ng-src, gleiche Wirkung ausprobiert habe. Update II: Wenn ich ein HTTPS verwende, bleibt das src-Attribut und das Bild wird angezeigt. Dies ist akzeptabel, da es auf HTTPS in der Produktion läuft, aber ich würde immer noch gerne wissen, warum die Deaktivierung von $ sce nicht funktioniert.

HTML als vom Browser gesehen (Gehalt an slide.body)

<div class="row"> 
    <div class="col-md-6 visible-md visible-lg"> 
     <img alt="none" class="img-responsive"> 
    </div> 
    <div class="col-xs-12 col-md-6"> 
     <div class="itx-article-header"> 
      <h1>Sulvat Quis 1</h1> 

      <h2>– Nullam dictum ac enim</h2> 

     </div> 
     <p>Proin quis justo vel felis varius sodales sit amet ut diam.</p> 
    </div> 
</div> 

JADE (HTML)

.my-carousel(ng-controller='CarouselCtrl') 
    carousel(interval='myInterval') 
     slide(ng-repeat='slide in slides', active='slide.active') 
      .my-carousel-item(ng-bind-html='slide.body') 

Winkelregler

.controller('CarouselCtrl', ['$sce', 'Article', '$scope', 
    function($sce, Article, $scope) { 
     $scope.myInterval = -1; 
     $scope.slides = Article.query(
      {category: 'carousel'}, 
      function(data){ 
       for (var i = 0; i < data.length; i++) { 
        $scope.slides[i].body = $sce.trustAsHtml(data[i].body);      
       } 
      }, 
      function() { 
       // Fail 
      }); 
    }]) 

Beispiel JSON Antwort (Folie) Sorry über die breite Box, hat es nicht geschafft, es zu formatieren.

{ 
"cmarId": 16, 
"corp": { 
    "corpId": 2, 
    "guiSelected": false 
}, 
"createdAt": "Sep 27, 2013", 
"articleTag": "slide-1", 
"headline": "Slide 1", 
"highlighted": false, 
    "body": "\u003cdiv class\u003d\"container my-carousel-container-small\"\u003e\r\n\u003cdiv class\u003d\"row\"\u003e\r\n\u003cdiv class\u003d\"col-md-6 visible-md visible-lg\"\u003e\u003cimg ng-src\u003d\"img/illustrative/laptop.jpg\" alt\u003d\"none\" class\u003d\"img-responsive\" /\u003e\u003c/div\u003e\r\n\u003cdiv class\u003d\"col-xs-12 col-md-6\"\u003e\r\n\u003cdiv class\u003d\"my-article-header\"\u003e\r\n\u003ch1\u003eSulvat Quis 1\u003c/h1\u003e\r\n\u003ch2\u003e– Nullam dictum ac enim\u003c/h2\u003e\r\n\u003c/div\u003e\r\n\u003cp\u003eProin quis justo vel felis varius sodales sit amet ut diam. Fusce auctor sapien nec purus sagittis, in venenatis turpis luctus. Nullam dictum ac enim sed commodo. Vivamus et placerat sapien.\u003c/p\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e\r\n\u003c/div\u003e", 
"articlePriority": 0, 
"category": { 
    "cmcaId": 9, 
    "corp": { 
     "corpId": 2, 
     "guiSelected": false 
    }, 
    "name": "carousel", 
    "visibleInMenu": false 
}, 
"published": true 

}

+0

Haben Sie versucht, 'ng-src' hochgeladen angezeigt werden? – kubuntu

+0

Yupp, immer noch vermisst. –

+0

Können Sie uns zeigen, was Sie mit '$ sce.trustAsHtml()' gemacht haben? –

Antwort

9

Das Stück, das Sie hier sind vermisst wird, um die Bild-URL über $sce.trustAsResourceURL(); vertrauen. Die entsprechende Dokumentation finden Sie unter here.

BEARBEITEN: Es scheint auch, dass Sie den ng-src-Wert nicht in Anführungszeichen setzen (sowie die erforderlichen Anführungszeichen, da es ein HTML-Attribut ist). Das wird nicht funktionieren - ng-src erwartet eine JavaScript-Zeichenkette als Endergebnis des Ausdrucks und Sie liefern es mit einem ungültigen Javascript-Literal.

+0

Soweit ich sehe kann man nur die Bild-URL in die oben genannte Methode schicken. Ich arbeite mit einem ganzen String von HTML, von dem ich nicht weiß, ob/wo das Bild ist. In Bezug auf dein Update, wo fehlen Zitate? –

+0

Wenn ich den HTML-Blob nicht schrecklich falsch gelesen habe, hat ng-src \ u003d \ "img/illustrative/laptop.jpg \" nur die äußeren Anführungszeichen. –

+0

Wie für die URL, du bist irgendwie dort stecken. Sie können die Bereinigung entweder deaktivieren (nicht empfohlen) oder Sie können die Antwort restrukturieren, um Ihnen eine Liste der URLs zu geben, denen Sie aus verschiedenen Gründen vertrauen müssen (Ressource vs. Link). –

2

Referenz: Die AngularJS documentation for $sanitize hat eine Demo. Wenn Sie in dieser Demo src anstelle von ng-src und ng-bind-html für eine Funktion verwenden (die ein Objekt von $sce.trustAsHtml() zurückgibt), wird das Bild wie erwartet angezeigt.


Vorgeschlagene Änderungen: Ich würde zuerst ng-src mit src ersetzen.

Dann würde ich

for (var i = 0; i < data.length; i++) { 
    $scope.slides[i].body = $sce.trustAsHtml(data[i].body);      
} 

zu

for (var i = 0; i < data.length; i++) { 
    $scope.slides[i].body = function() { 
     return $sce.trustAsHtml(data[i].body); 
    }; 
} 

Schließlich ändern diese

.my-carousel-item(ng-bind-html='slide.body') 

zu

.my-carousel-item(ng-bind-html='slide.body()') 
ändern würde

Ich habe das selbst nicht getestet, aber bitte lassen Sie mich wissen, ob das funktioniert.


Edit (2013.11.02):Typo fix - Ich habe return zur Funktion Beispiel. Der Code sollte jetzt wie erwartet funktionieren.

+0

Ihre Antwort, die angularen Bindungen nicht zu verwenden, scheint nicht die richtige Route zu gehen. Warum würden Sie auf die Bindungen verzichten, um das Feature zu umgehen? –

+0

Ich weiß es ehrlich gesagt nicht. Ich habe 'none' in das Beispiel eingefügt und es hat funktioniert. Sobald ich 'src' in' ng-src' änderte, fiel das Bild auf alternativen Text zurück. –

+0

@TylerEich: Wenn Sie das Update lesen (was vor Ihrer Antwort geschrieben wurde), werden Sie sehen, dass ich tatsächlich sowohl src als auch ng-src ausprobiert habe, kein Unterschied. Also denke ich, dass Ihre Art, die Bindungen zu umgehen, dafür sorgt, dass es funktioniert. –

2

Sehen Sie diesen Kommentar auf der AngularUI Diskussion: https://github.com/angular-ui/bootstrap/issues/813#issuecomment-25760432

Es ist eine Richtlinie, die die alte bind-html-unsafe Merkmal reimplementiert, die vorhanden war in AngularJS 1.2 vor. Am Ende wird das gleiche wie oben vorgeschlagen, aber mit einem Minimum an Aufwand. Sie könnten also einfach ng-bind-html-unsafe verwenden und Ihren Code nicht lesbarer machen, indem Sie die $ sce-Umgehung in Ihrem Hauptcode hinzufügen müssen.

Siehe auch diese Frage Stackoverflow:

1

Nach Stunden der Suche, wie man Bild über WYSIWYG-Editor für meine CMS App ich fand diese

.filter('toTrusted', ['$sce', function($sce) { 
    return function(text) { 
     return $sce.trustAsHtml(text); 
    }; 
}]); 
<div ng-bind-html="data | toTrusted"></div> 

Hoffe, es hilft