Wie füge ich HTML ein, wenn ng-bind-html-unsafe entfernt wurde?

265

Ich versuche, den $sanitizeAnbieter und die ng-bind-htm-unsafeDirektive zu verwenden, damit mein Controller HTML in ein DIV einfügen kann.

Ich kann es jedoch nicht zum Laufen bringen.

<div ng-bind-html-unsafe="{{preview_data.preview.embed.html}}"></div>

Ich habe festgestellt, dass es daran liegt, dass es aus AngularJS entfernt wurde (danke).

Aber ohne ng-bind-html-unsafebekomme ich diesen Fehler:

http://errors.angularjs.org/undefined/$sce/unsafe

Metallaureat
quelle
Es gibt eine einfache Lösung für 1.2.23+, siehe Beitrag
John Henckel

Antworten:

123
  1. Sie müssen sicherstellen, dass sanitize.js geladen ist. Laden Sie es beispielsweise von https://ajax.googleapis.com/ajax/libs/angularjs/[LAST_VERSION‹/angular-sanitize.min.js
  2. Sie müssen das ngSanitizeModul in Ihr app Beispiel aufnehmen:var app = angular.module('myApp', ['ngSanitize']);
  3. Sie müssen nur mit ng-bind-htmldem ursprünglichen htmlInhalt binden . Sie müssen nichts anderes in Ihrem Controller tun. Das Parsen und Konvertieren erfolgt automatisch durch die ngBindHtmlDirektive. (Lesen Sie dazu den How does it workAbschnitt: $ sce ). Also, in deinem Fall <div ng-bind-html="preview_data.preview.embed.html"></div>würde die Arbeit machen.
p.matsinopoulos
quelle
3
Dies ist die sauberste Option, um dies sicher zu tun. Es kam mit mehr Abhängigkeiten, aber es geht um Sicherheit, also kein Zögern!
Pierre Maoui
Verwenden Sie dies mit ionischen 1.0.0-beta.13
Jasonflaherty
3
Dies funktioniert bei einigen Tags wie Eingaben nicht. Natürlich gibt es keinen einfachen Weg, dies zu umgehen. Wirklich frustrierend.
Casey
Der gebräuchlichste und sicherste Weg. Ziehen Sie dies vor, wenn Sie die Verwendung von bind-html in verschiedenen Ansichten planen.
Eduardobursa
350

Anstatt eine Funktion in Ihrem Bereich zu deklarieren, wie von Alex vorgeschlagen, können Sie sie in einen einfachen Filter konvertieren:

angular.module('myApp')
    .filter('to_trusted', ['$sce', function($sce){
        return function(text) {
            return $sce.trustAsHtml(text);
        };
    }]);

Dann können Sie es so verwenden:

<div ng-bind-html="preview_data.preview.embed.html | to_trusted"></div>

Und hier ist ein funktionierendes Beispiel: http://jsfiddle.net/leeroy/6j4Lg/1/

Leeroy Brun
quelle
3
Ich habe eine kleine Sammlung nützlicher Werkzeuge für Winkel auf Github . Ich werde diesen Filter in diese Werkzeuge aufnehmen, wenn Sie nichts dagegen haben. Dies ist meiner Meinung nach die beste Lösung, wenn Sie dem HTML vertrauen.
Capaj
@ Capaj Kein Problem, aber wenn Sie einen Link zu dieser Antwort hinzufügen, wäre dies sehr dankbar. :-) stackoverflow.com/a/21254635
Leeroy Brun
Sehr schön. Dies funktioniert wie ein Zauber bei verschachtelten Wiederholungen!
Jelle Verzijden
Dies scheint eine VIEL bessere Lösung zu sein als die Codierung für jeden Controller. Nur ein kurzer Filter und fertig! Ich habe es mit sich wiederholenden Tabellenzeilen verwendet, einfach wie Torte ... <td ng-bind-html="representative.primary | to_trusted"></td>
Phil Nicholas
2
angle.module ('myApp'). filter ('trustAsHtml', ['$ sce', Funktion ($ sce) {return $ sce.trustAsHtml}]);
Bradw2k
275

Sie haben angegeben, dass Sie Angular 1.2.0 verwenden ... da einer der anderen angegebenen Kommentare ng-bind-html-unsafeveraltet ist.

Stattdessen möchten Sie Folgendes tun:

<div ng-bind-html="preview_data.preview.embed.htmlSafe"></div>

Fügen Sie in Ihren Controller den $sceDienst ein und markieren Sie den HTML-Code als "vertrauenswürdig":

myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
  // ...
  $scope.preview_data.preview.embed.htmlSafe = 
     $sce.trustAsHtml(preview_data.preview.embed.html);
}

Beachten Sie, dass Sie 1.2.0-rc3 oder neuer verwenden möchten. (Sie haben einen Fehler in rc3 behoben, der "Beobachter" daran hinderte, ordnungsgemäß mit vertrauenswürdigem HTML zu arbeiten.)

ijprest
quelle
2
Ich habe versucht, das oben genannte zu verwenden, aber es bricht meinen Code. Anscheinend müssen Sie '$ scope' vor der Funktionsdefinition voranstellen - vielleicht wurde es einmal "verstanden", aber nicht mehr. Folgendes sollte funktionieren:myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
Dexygen
4
Weitere Informationen zu $ ​​sce finden Sie hier , um der Neugier nachzugehen ! ;)
echtfafa
5
Beachten Sie, dass dies wahrscheinlich ein XSS-Sicherheitsproblem in Ihrem Code verursacht. Eine alternative, sicherere Lösung finden Sie in der ngSanitizeunten vorgeschlagenen Antwort ( stackoverflow.com/a/25679834/22227 ).
Martin Probst
Warum dies eine schlechte Idee ist: docs.google.com/presentation/d/…
user857990
trustAsHtmltut, was es sagt, es vertraut jedem eingehenden HTML-Code, der zu Cross-Site Scripting (XSS) -Angriffen führen kann
Aleksey Solovey
112

Für mich ist die einfachste und flexibelste Lösung:

<div ng-bind-html="to_trusted(preview_data.preview.embed.html)"></div>

Und fügen Sie Ihrem Controller eine Funktion hinzu:

$scope.to_trusted = function(html_code) {
    return $sce.trustAsHtml(html_code);
}

Vergessen Sie nicht, $scedie Initialisierung Ihres Controllers zu ergänzen .

Alex
quelle
Es scheint einfacher zu sein, dass der Controller das vertrauenswürdige HTML in $ scope zurückgegeben hat
meffect
1
Dies kann eine Endlosschleife auf $ sce werfen. Führen Sie dazu Folgendes aus: $ scope.trusted = {}; $ scope.to_trusted = function (html_code) {$ scope.trusted [html_code] || zurückgeben ($ scope.trusted [html_code] = $ sce.trustAsHtml (html_code)); };
AO_
1
Jede Lösung, bei der HTML als vertrauenswürdig gesegnet wird, führt zu einer XSS-Sicherheitsanfälligkeit. In der Antwort, die ngSanitize unten vorschlägt (stackoverflow.com/a/25679834/22227), finden Sie eine sicherere Lösung.
Michele Spagnuolo
65

Die beste Lösung dafür ist meiner Meinung nach:

  1. Erstellen Sie einen benutzerdefinierten Filter, der sich beispielsweise in einer Datei common.module.js befinden kann und in Ihrer gesamten App verwendet wird:

    var app = angular.module('common.module', []);
    
    // html filter (render text as html)
    app.filter('html', ['$sce', function ($sce) { 
        return function (text) {
            return $sce.trustAsHtml(text);
        };    
    }])
  2. Verwendungszweck:

    <span ng-bind-html="yourDataValue | html"></span>

Nun - ich verstehe nicht, warum die Richtlinie ng-bind-htmlnicht trustAsHtmlTeil ihrer Funktion ist - scheint mir ein bisschen dumm, dass dies nicht der Fall ist

Wie auch immer - so mache ich das - 67% der Zeit funktioniert es immer.

Paul
quelle
Sie können den folgenden regulären Ausdruck verwenden, um zu suchen und zu ersetzen: regulärer Ausdruck: ng-bind-html-unsafe = "((? :(?!").) *) "Ersetzen: ng-bind-html =" ($ 1) | html "mit dem obigen Filter.
George Donev
2
Jede Lösung, bei der HTML als vertrauenswürdig gesegnet wird, führt zu einer XSS-Sicherheitsanfälligkeit. In der Antwort, die ngSanitize unten vorschlägt (stackoverflow.com/a/25679834/22227), finden Sie eine sicherere Lösung.
Michele Spagnuolo
7

Sie können Ihre eigene einfache unsichere HTML-Bindung erstellen. Wenn Sie Benutzereingaben verwenden, kann dies natürlich ein Sicherheitsrisiko darstellen.

App.directive('simpleHtml', function() {
  return function(scope, element, attr) {
    scope.$watch(attr.simpleHtml, function (value) {
      element.html(scope.$eval(attr.simpleHtml));
    })
  };
})
Jason Goemaat
quelle
Könnte diese Richtlinie nicht auch die verwenden $sce.trustAsHtml?
Kontur
5

Sie müssen {{}} nicht in ng-bind-html-unsafe verwenden:

<div ng-bind-html-unsafe="preview_data.preview.embed.html"></div>

Hier ist ein Beispiel: http://plnkr.co/edit/R7JmGIo4xcJoBc1v4iki?p=preview

Der Operator {{}} ist im Wesentlichen nur eine Abkürzung für ng-bind. Was Sie also versucht haben, entspricht einer Bindung innerhalb einer Bindung, die nicht funktioniert.

ksimons
quelle
Wenn ich es jedoch entferne, wird mir nichts injiziert. Und die Dokumente sind sehr verwirrend, wenn
metalaureate
Sehr komisch. Ich habe es gerade getestet, um sicherzugehen, und für mich hat es wie erwartet funktioniert. Ich bin damit einverstanden, dass die einzelnen {} in den Dokumenten etwas verwirrend sind, aber sie sind als Darstellung eines Ausdrucks gedacht, nicht als Literale in der Zeichenfolge. Ich habe meine Antwort mit einem funktionierenden Plunk aktualisiert.
ksimons
Wenn Sie bereits 1.2.0 verwenden, lesen
ksimons
2
Ich benutze 1.2. :( Grrr! Wie kann man unsicheres HTML einfügen
Metalaureate
Der {{}}Operator hat mein Problem mit fehlgeschlagener Bindung verursacht, danke für den Hinweis!
Campbeln
2

Ich hatte ein ähnliches Problem. Ich konnte immer noch keinen Inhalt von meinen auf github gehosteten Markdown-Dateien erhalten.

Nach dem Einrichten einer Whitelist (mit hinzugefügter Github-Domain) für den $ sceDelegateProvider in app.js funktionierte dies wie ein Zauber.

Beschreibung: Verwenden Sie eine Whitelist, anstatt sie als vertrauenswürdig zu verpacken, wenn Sie Inhalte von einer anderen URL laden.

Docs: $ sceDelegateProvider und ngInclude (zum Abrufen, Kompilieren und Einschließen eines externen HTML-Fragments)

Lahmizzar
quelle
2

Strict Contextual Escaping kann vollständig deaktiviert werden, sodass Sie HTML mit injizieren können ng-html-bind. Dies ist eine unsichere Option, aber beim Testen hilfreich.

Beispiel aus der AngularJS-Dokumentation zu$sce :

angular.module('myAppWithSceDisabledmyApp', []).config(function($sceProvider) {
  // Completely disable SCE.  For demonstration purposes only!
  // Do not use in new projects.
  $sceProvider.enabled(false);
});

Wenn Sie den obigen Konfigurationsabschnitt an Ihre App anhängen, können Sie HTML einfügen ng-html-bind, aber wie im Dokument erwähnt:

SCE bietet Ihnen viele Sicherheitsvorteile bei geringem Codierungsaufwand. Es wird viel schwieriger sein, eine SCE-deaktivierte Anwendung entweder selbst zu sichern oder SCE zu einem späteren Zeitpunkt zu aktivieren. Es kann sinnvoll sein, SCE für Fälle zu deaktivieren, in denen viel Code vorhanden ist, der vor der Einführung von SCE geschrieben wurde, und Sie jeweils ein Modul migrieren.

Sean Fahey
quelle
Gut zu wissen, aber definitiv etwas, das mit Vorsicht behandelt werden sollte.
Bilderstürmer
2

Sie können einen solchen Filter verwenden

angular.module('app').filter('trustAs', ['$sce', 
    function($sce) {
        return function (input, type) {
            if (typeof input === "string") {
                return $sce.trustAs(type || 'html', input);
            }
            console.log("trustAs filter. Error. input isn't a string");
            return "";
        };
    }
]);

Verwendung

<div ng-bind-html="myData | trustAs"></div>

Es kann für andere Ressourcentypen verwendet werden, z. B. für den Quelllink für Iframes und andere hier deklarierte Typen

BotanMan
quelle