Dengan ng-bind-html-tidak aman dihapus, bagaimana cara saya menyuntikkan HTML?

265

Saya mencoba menggunakan $sanitizepenyedia danng-bind-htm-unsafe arahan untuk memungkinkan pengontrol saya untuk menyuntikkan HTML ke dalam DIV.

Namun, saya tidak bisa membuatnya bekerja.

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

Saya menemukan bahwa itu karena dihapus dari AngularJS (terima kasih).

Tapi tanpa ng-bind-html-unsafe, saya mendapatkan kesalahan ini:

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

metalaureate
sumber
Ada solusi sederhana untuk 1.2.23+, lihat posting
John Henckel

Jawaban:

123
  1. Anda perlu memastikan bahwa sanitize.js dimuat. Misalnya, muat dari https://ajax.googleapis.com/ajax/libs/angularjs/[LAST_VERSION[/angular-sanitize.min.js
  2. Anda perlu memasukkan ngSanitizemodul pada app mis Anda :var app = angular.module('myApp', ['ngSanitize']);
  3. Anda hanya perlu mengikat dengan konten ng-bind-htmlasli html. Tidak perlu melakukan hal lain di controller Anda. Penguraian dan konversi secara otomatis dilakukan oleh ngBindHtmlarahan. (Baca How does it workbagian ini: $ sce ). Jadi, dalam kasus Anda <div ng-bind-html="preview_data.preview.embed.html"></div>akan melakukan pekerjaan.
p.matsinopoulos
sumber
3
Ini adalah opsi terbersih untuk melakukannya dengan aman. Itu datang dengan lebih banyak ketergantungan tetapi ini tentang keamanan jadi tidak ragu-ragu!
Pierre Maoui
Menggunakan ini dengan ionic 1.0.0-beta.13
jasonflaherty
3
Ini tidak berfungsi dengan beberapa tag, seperti input. Tentu saja tidak ada cara mudah untuk menyiasatinya. Benar-benar membuat frustrasi.
Casey
Cara paling umum dan aman. Lebih suka ini jika Anda berencana menggunakan bind-html dalam tampilan berbeda.
eduardobursa
350

Alih-alih mendeklarasikan fungsi dalam cakupan Anda, seperti yang disarankan oleh Alex, Anda dapat mengubahnya menjadi filter sederhana:

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

Maka Anda dapat menggunakannya seperti ini:

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

Dan di sini adalah contoh kerja: http://jsfiddle.net/leeroy/6j4Lg/1/

Leeroy Brun
sumber
3
Saya memiliki koleksi kecil alat yang berguna untuk angular di github , saya akan memasukkan filter ini ke dalam alat tersebut jika Anda tidak keberatan. Ini adalah IMHO solusi terbaik ketika Anda mempercayai html.
Capaj
@Capaj Tidak masalah, tetapi jika Anda menambahkan tautan ke jawaban ini, ini akan sangat dihargai. :-) stackoverflow.com/a/21254635
Leeroy Brun
Sangat bagus. ini bekerja seperti pesona pada pengulangan bersarang!
Jelle Verzijden
Ini sepertinya solusi yang JAUH lebih baik daripada coding untuk setiap controller. Cukup filter cepat dan selesai! Saya menggunakannya dengan mengulangi baris tabel, sesederhana pai .... <td ng-bind-html="representative.primary | to_trusted"></td>
Phil Nicholas
2
angular.module ('myApp'). filter ('trustAsHtml', ['$ sce', fungsi ($ sce) {return $ sce.trustAsHtml}]);
bradw2k
275

Anda mengindikasikan bahwa Anda menggunakan Angular 1.2.0 ... sebagai salah satu komentar lain yang ditunjukkan, ng-bind-html-unsafe telah usang.

Sebagai gantinya, Anda ingin melakukan sesuatu seperti ini:

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

Di controller Anda, menyuntikkan $scelayanan, dan tandai HTML sebagai "tepercaya":

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

Perhatikan bahwa Anda ingin menggunakan 1.2.0-rc3 atau yang lebih baru. (Mereka memperbaiki bug di rc3 yang mencegah "pengamat" bekerja dengan baik pada HTML tepercaya.)

ijprest
sumber
2
Saya mencoba menggunakan di atas tetapi merusak kode saya. Tampaknya Anda perlu menambahkan '$ scope' sebelum definisi fungsi - mungkin itu "dipahami" pada satu waktu, tetapi tidak lagi. Yang berikut ini harus berfungsi:myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
Dexygen
4
Anda dapat melihat informasi lebih lanjut tentang $ sce di sini hanya untuk mengejar rasa ingin tahu! ;)
genuinefafa
5
Perhatikan bahwa ini kemungkinan akan menyebabkan masalah keamanan XSS dalam kode Anda. Lihat jawaban yang menyarankan di ngSanitizebawah ini ( stackoverflow.com/a/25679834/22227 ) untuk alternatif, perbaikan yang lebih aman.
Martin Probst
Mengapa ini adalah ide yang buruk: docs.google.com/presentation/d/…
user857990
trustAsHtmlmelakukan apa yang tertulis, itu mempercayai setiap kode yang masuk html, yang dapat mengakibatkan Cross-Site Scripting (XSS) serangan
Aleksey Solovey
112

Bagi saya, solusi paling sederhana dan paling fleksibel adalah:

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

Dan tambahkan fungsi ke controller Anda:

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

Jangan lupa tambahkan $sceinisialisasi pengontrol Anda.

Alex
sumber
Tampaknya lebih mudah untuk memiliki controller mengembalikan html tepercaya dalam lingkup $
meffect
1
Ini dapat melempar infinite loop pada $ sce, melakukan sesuatu seperti: $ scope.trusted = {}; $ scope.to_trusted = function (html_code) {return $ scope.trusted [html_code] || ($ scope.trusted [html_code] = $ sce.trustAsHtml (html_code)); };
AO_
1
Setiap solusi yang melibatkan memberkati HTML sebagai tepercaya memperkenalkan kerentanan XSS. Silakan lihat jawaban yang menyarankan ngSanitize di bawah ini (stackoverflow.com/a/25679834/22227) untuk perbaikan yang lebih aman.
Michele Spagnuolo
65

Solusi terbaik untuk ini menurut saya adalah ini:

  1. Buat filter khusus yang dapat berupa file common.module.js misalnya - digunakan di seluruh aplikasi Anda:

    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. Pemakaian:

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

Sekarang - saya tidak mengerti mengapa arahan ng-bind-htmltidaktrustAsHtml sebagai bagian dari fungsinya - tampaknya agak bodoh bagi saya bahwa itu tidak

Ngomong-ngomong - itulah cara saya melakukannya - 67% dari waktu, itu berhasil setiap saat.

Paul
sumber
Anda dapat menggunakan regex berikut untuk melakukan pencarian dan mengganti: regex: ng-bind-html-unsafe = "((? :( ?!").) *) "Pengganti: ng-bind-html =" ($ 1) | html "dengan filter di atas.
George Donev
2
Setiap solusi yang melibatkan memberkati HTML sebagai tepercaya memperkenalkan kerentanan XSS. Silakan lihat jawaban yang menyarankan ngSanitize di bawah ini (stackoverflow.com/a/25679834/22227) untuk perbaikan yang lebih aman.
Michele Spagnuolo
7

Anda dapat membuat pengikatan html sederhana yang tidak aman sendiri, tentu saja jika Anda menggunakan input pengguna, itu bisa menjadi risiko keamanan.

App.directive('simpleHtml', function() {
  return function(scope, element, attr) {
    scope.$watch(attr.simpleHtml, function (value) {
      element.html(scope.$eval(attr.simpleHtml));
    })
  };
})
Jason Goemaat
sumber
Tidak bisakah arahan ini juga menggunakan $sce.trustAsHtml?
kontur
5

Anda tidak perlu menggunakan {{}} di dalam ng-bind-html-unsafe:

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

Berikut ini contohnya: http://plnkr.co/edit/R7JmGIo4xcJoBc1v4iki?p=preview

Operator {{}} pada dasarnya hanyalah singkatan untuk ng-bind, jadi apa yang Anda coba sama dengan penjilidan di dalam penjilidan, yang tidak berfungsi.

ksimons
sumber
Namun, jika saya menghapusnya, saya tidak mendapatkan suntikan. Dan dokumennya
metalaureate
Sangat aneh. Saya baru saja mengujinya untuk memastikan dan bagi saya itu berfungsi seperti yang diharapkan. Saya setuju bahwa {} sedikit membingungkan dalam dokumen, tetapi mereka dimaksudkan sebagai representasi ekspresi, bukan sebagai literal dalam string. Saya telah memperbarui jawaban saya dengan plunk yang berfungsi.
ksimons
Juga, jika Anda sudah menggunakan 1.2.0, lihat komentar di sini karena ng-bind-html-unsafe telah dihapus: docs.angularjs.org/api/ng.directive:ngBindHtml
ksimons
2
Saya menggunakan 1.2. !? :( Grrr Bagaimana seseorang dapat menyuntikkan HTML tidak aman saya mendapatkan error ini tanpa itu: errors.angularjs.org/undefined/$sce/unsafe
metalaureate
The {{}}operator adalah menyebabkan masalah saya dengan mengikat gagal, terima kasih untuk petunjuk yang!
Campbeln
2

Saya punya masalah serupa. Masih tidak bisa mendapatkan konten dari file penurunan harga saya yang diinangi di github.

Setelah menyiapkan daftar putih (dengan domain github ditambahkan) ke $ sceDelegateProvider di app.js itu berfungsi seperti pesona.

Deskripsi: Menggunakan daftar putih alih-alih membungkus sebagai tepercaya jika Anda memuat konten dari url yang berbeda.

Documents: $ sceDelegateProvider dan ngInclude (untuk mengambil, mengkompilasi, dan memasukkan fragmen HTML eksternal)

Lahmizzar
sumber
2

Escaping Kontekstual yang Ketat dapat dinonaktifkan sepenuhnya, memungkinkan Anda untuk menyuntikkan html menggunakan ng-html-bind. Ini adalah opsi yang tidak aman, tetapi sangat membantu saat pengujian.

Contoh dari dokumentasi AngularJS pada$sce :

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

Melampirkan bagian konfigurasi di atas ke aplikasi Anda akan memungkinkan Anda menyuntikkan html ke dalamnya ng-html-bind, tetapi seperti yang dinyatakan oleh dokumen:

SCE memberi Anda banyak manfaat keamanan untuk sedikit pengkodean overhead. Akan jauh lebih sulit untuk mengambil aplikasi yang dinonaktifkan oleh SCE dan mengamankannya sendiri atau mengaktifkan SCE di tahap selanjutnya. Mungkin masuk akal untuk menonaktifkan SCE untuk kasus-kasus di mana Anda memiliki banyak kode yang sudah ada yang ditulis sebelum SCE diperkenalkan dan Anda memigrasikannya sebuah modul pada suatu waktu.

Sean Fahey
sumber
Baik untuk diketahui, tetapi pasti sesuatu yang harus ditangani dengan hati-hati.
iconoclast
2

Anda dapat menggunakan filter seperti ini

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

pemakaian

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

dapat digunakan untuk jenis sumber daya lainnya, misalnya tautan sumber untuk iframe dan jenis lain yang dideklarasikan di sini

Botanman
sumber