Як видалити ng-bind-html-небезопасно, як я вставлю HTML?


265

Я намагаюся використовувати $sanitize провайдер і ng-bind-htm-unsafeдирективу, щоб дозволити моєму контролеру вводити HTML у DIV.

Однак я не можу змусити його працювати.

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

Я виявив, що це тому, що його видалили з AngularJS (спасибі).

Але без цього ng-bind-html-unsafeя отримую цю помилку:

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


Існує просте рішення для 1.2.23+, див. Пост
Джон Генкель

Відповіді:


123
  1. Вам потрібно переконатися, що sanitize.js завантажений. Наприклад, завантажте його з https://ajax.googleapis.com/ajax/libs/angularjs/ evidenceLAST_VERSIONSense/angular-sanitize.min.js
  2. вам потрібно включити ngSanitizeмодуль, app наприклад:var app = angular.module('myApp', ['ngSanitize']);
  3. вам просто потрібно зв’язати ng-bind-htmlоригінальний htmlвміст. Не потрібно нічого робити у своєму контролері. Синтаксичний аналіз та перетворення здійснюються автоматично ngBindHtmlдирективою. (Прочитайте How does it workрозділ на цьому: $ sce ). Отже, у вашому випадку <div ng-bind-html="preview_data.preview.embed.html"></div>зробили б роботу.

3
Це найчистіший варіант зробити це безпечно. Він прийшов з більшою залежністю, але це стосується безпеки, тому не вагайтеся!
П’єр Мауї

Використовуючи це за допомогою іонного 1.0.0-beta.13
jasonflaherty

3
Це не працює з деякими тегами, як-от введення. Звичайно, немає простого способу обійти це. Дійсно розчаровує.
Кейсі

Найпоширеніший і безпечний спосіб. Віддайте перевагу цьому, якщо ви плануєте використовувати bind-html в різних переглядах.
eduardobursa

350

Замість того, щоб оголосити функцію у вашому обсязі, як запропонував Алекс, ви можете її перетворити на простий фільтр:

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

Тоді ви можете використовувати його так:

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

І ось робочий приклад: http://jsfiddle.net/leeroy/6j4Lg/1/


3
У мене невелика колекція корисних інструментів для кутових на github , я включу цей фільтр у ці інструменти, якщо ви не заперечуєте. Це найкраще рішення IMHO, коли ви довіряєте HTML.
Капай

@Capaj Немає проблем, але якщо ви додасте посилання на цю відповідь, це буде дуже вдячно. :-) stackoverflow.com/a/21254635
Leeroy Brun

Дуже хороша. це працює як шарм на вкладених повторах!
Jelle Verzijden

Це здається набагато кращим рішенням, ніж кодування для кожного контролера. Просто швидкий фільтр і готово! Я використовував це з повторенням рядків таблиці, простий як пиріг .... <td ng-bind-html="representative.primary | to_trusted"></td>
Філ Ніколас

2
angular.module ('myApp'). filter ('trustAsHtml', ['$ sce', функція ($ sce) {return $ sce.trustAsHtml}]);
bradw2k

275

Ви вказали, що ви використовуєте Angular 1.2.0 ... як один із інших коментарів, ng-bind-html-unsafeзастарілий.

Натомість вам захочеться зробити щось подібне:

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

У своєму контролері введіть $sceслужбу та позначте HTML як "довірений":

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

Зауважте, що ви хочете використовувати 1.2.0-rc3 або новішу версію. (Вони виправили помилку в rc3, яка заважала спостерігачам працювати належним чином на надійному HTML.)


2
Я спробував використати вище, але це порушує мій код. Здається, вам потрібно додати «$ range» перед визначенням функції - можливо, це було «зрозуміло» свого часу, але вже не. Слід працювати так:myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
Dexygen

4
Ви можете подивитися більше інформації про $ sce тут просто для цікавості! ;)
truefafa

5
Зауважте, що це, ймовірно, спричинить проблему безпеки XSS у вашому коді. Дивіться запропоновану ngSanitizeнижче відповідь ( stackoverflow.com/a/25679834/22227 ) для альтернативного, більш безпечного виправлення.
Мартін Пробст

Чому це погана ідея: docs.google.com/presentation/d/…
user857990

trustAsHtmlробить те, що говорить, довіряє будь-який вхідний html-код, який може спричинити напади міжсайтового сценарію (XSS)
Олексій Соловей

112

Для мене найпростішим та гнучким рішенням є:

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

І додайте функцію до свого контролера:

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

Не забудьте додати $sceдо ініціалізації вашого контролера.


Більш очевидним здається, що контролер повернув довірений html у $
range

1
Це може кинути нескінченний цикл на $ sce, зробити щось на кшталт: $ range.trusted = {}; $ range.to_trusted = функція (html_code) {return $ range.trusted [html_code] || ($ range.trusted [html_code] = $ sce.trustAsHtml (html_code)); };
AO_

1
Кожне рішення, що передбачає благословення HTML як надійного, вводить вразливість XSS. Дивіться відповідь, що пропонує ngSanitize нижче (stackoverflow.com/a/25679834/22227) для більш безпечного виправлення.
Мішель Спагньоло

65

Найкраще рішення, на мою думку, це:

  1. Створіть спеціальний фільтр, який може бути, наприклад, у файлі common.module.js - який використовується у вашому додатку:

    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. Використання:

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

Тепер - я не бачу, чому директива ng-bind-htmlцього не робитьtrustAsHtml є частиною своєї функції - мені здається трохи непростим, що це не так

У будь-якому випадку - так я і роблю - 67% часу, це працює колись.


Ви можете використовувати наступний регулярний вираз для пошуку та заміни: regex: ng-bind-html-unsafe = "((? :( ?!"). *) "Заміна: ng-bind-html =" ($ 1) | html "із зазначеним вище фільтром.
Георгій Донев

2
Кожне рішення, що передбачає благословення HTML як надійного, вводить вразливість XSS. Дивіться відповідь, що пропонує ngSanitize нижче (stackoverflow.com/a/25679834/22227) для більш безпечного виправлення.
Мішель Спагньоло

7

Ви можете створити власну просту небезпечну HTML-прив'язку, звичайно, якщо ви використовуєте введення користувача, це може бути ризиком для безпеки.

App.directive('simpleHtml', function() {
  return function(scope, element, attr) {
    scope.$watch(attr.simpleHtml, function (value) {
      element.html(scope.$eval(attr.simpleHtml));
    })
  };
})

Чи не могла ця директива також використовувати $sce.trustAsHtml?
kontur

5

Вам не потрібно використовувати {{}} всередині ng-bind-html-unsafe:

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

Ось приклад: http://plnkr.co/edit/R7JmGIo4xcJoBc1v4iki?p=preview

Оператор {{}} по суті є лише скороченням для ng-bind, тому те, що ви намагалися, означає прив'язку всередині прив'язки, яка не працює.


Однак якщо я її видаляю, мені нічого не вводять. І документи дуже заплутані, використовуючи один} docs-angularjs-org-dev.appspot.com/api/…
metalaureate

Дуже дивно. Я щойно перевірив це, і для мене він працював так, як очікувалося. Я погоджуюся, що сингли {} трохи заплутані в документах, але вони мають на увазі представлення виразу, а не як літерали в рядку. Я оновив свою відповідь робочим плунком.
ksimons

Крім того, якщо ви вже використовуєте 1.2.0, дивіться коментарі, як видалено ng-bind-html-unsafe: docs.angularjs.org/api/ng.directive:ngBindHtml
ksimons

2
Я використовую 1.2. :( Grrr! Як можна вводити небезпечний HTML? Я отримую цю помилку без неї: errors.angularjs.org/undefined/$sce/unsafe
metalaureate

{{}}Оператор викликає моє запитання з обов'язковим упущенням, спасибі за підказку!
Кемпбелн

2

У мене була подібна проблема. Ще не вдалося отримати вміст з моїх файлів розмітки, розміщених на github.

Після налаштування білого списку (із доданим доменом github) до $ sceDelegateProvider в app.js він працював як шарм.

Опис: Використання білого списку замість упаковки як надійного, якщо ви завантажуєте вміст з інших URL-адрес.

Документи: $ sceDelegateProvider та ngInclude (для отримання, компілювання та включення зовнішнього фрагмента HTML)


2

Суворе контекстне втечу може бути вимкнено повністю, що дозволяє вводити HTML за допомогою ng-html-bind. Це небезпечний варіант, але корисний при тестуванні.

Приклад з документації AngularJS про$sce :

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

Додавання вищевказаного розділу конфігурації до вашої програми дозволить ввести html у файл ng-html-bind, але як зазначає документ:

SCE дає безліч переваг безпеки для невеликого кодування накладних витрат. Набагато складніше буде взяти додаток, відключений SCE, або захистити його самостійно, або включити SCE на більш пізньому етапі. Можливо, має сенс відключити SCE у випадках, коли у вас є багато існуючого коду, який був написаний до введення SCE, і ви мігруєте їх одночасно модулем.


Приємно знати, але, безумовно, щось, з чим слід поводитися обережно.
іконоборство

2

Ви можете використовувати такий фільтр

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

використання

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

його можна використовувати для інших типів ресурсів, наприклад, посилання на джерело для iframes та інші типи, декларовані тут

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.