Как удалить HTML, если удалить ng-bind-html-unsafe?

237

Я пытаюсь использовать $sanitize provider и директиву 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

Теги:

10 ответов

105
Лучший ответ
  • Вам нужно убедиться, что загружен файл sanitize.js. Например, загрузите его из https://ajax.googleapis.com/ajax/libs/angularjs/[LAST_VERSION]/angular-sanitize.min.js
  • вам нужно включить модуль ngSanitize на ваш app например: var app = angular.module('myApp', ['ngSanitize']);
  • вам просто нужно связать с ng-bind-html исходным html контентом. Не нужно ничего делать в контроллере. Разбор и преобразование автоматически выполняются директивой ngBindHtml. (Прочитайте раздел How does it work по этому вопросу: $sce). Итак, в вашем случае <div ng-bind-html="preview_data.preview.embed.html"></div> выполнит эту работу.
  • 3
    Это самый чистый способ сделать это безопасно. У него было больше зависимостей, но речь идет о безопасности, поэтому без колебаний!
  • 0
    Используя это с ионной 1.0.0-бета.13
Показать ещё 2 комментария
348

Вместо объявления функции в вашей области действия, как было предложено Алексом, вы можете преобразовать ее в простой фильтр:

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
    У меня есть небольшая коллекция полезных инструментов для angular на github , я включу этот фильтр в эти инструменты, если вы не возражаете. Это ИМХО лучшее решение, когда вы доверяете HTML.
  • 0
    @Capaj Нет проблем, но если вы добавите ссылку на этот ответ, это будет с благодарностью. :-) stackoverflow.com/a/21254635
Показать ещё 5 комментариев
283

Вы указали, что используете 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
    Я попытался использовать выше, но это нарушает мой код. Кажется, вам нужно добавить предопределение «$ scope» перед определением функции - возможно, это было «понято» за один раз, но не больше. Должно работать следующее: myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
  • 4
    Вы можете посмотреть больше информации о $ sce здесь, просто чтобы заняться любопытством! ;)
Показать ещё 2 комментария
109

Для меня самое простое и гибкое решение:

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

И добавьте функцию к контроллеру:

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

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

  • 0
    Кажется более простым, чтобы контроллер возвратил доверенный HTML в $ scope
  • 1
    Это может создать бесконечный цикл в $ sce, сделать что-то вроде: $ scope.trusted = {}; $ scope.to_trusted = function (html_code) {вернуть $ scope.trusted [html_code] || ($ scope.trusted [html_code] = $ sce.trustAsHtml (html_code)); };
Показать ещё 1 комментарий
57

Лучшим решением для этого, на мой взгляд, является следующее:

  • Создайте настраиваемый фильтр, который может быть, например, в файле 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);
        };    
    }])
    
  • Применение:

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

Теперь - я не понимаю, почему директива ng-bind-html не является trustAsHtml как часть ее функции - кажется мне немного глупой, что она не

В любом случае - так, как я это делаю - 67% времени, он работает всегда.

  • 0
    Вы можете использовать следующее регулярное выражение для поиска и замены: regex: ng-bind-html-unsafe = "((? :( ?!").) *) "Replace: ng-bind-html =" ($ 1) | html "с указанным выше фильтром.
  • 1
    Каждое решение, которое включает в себя благословение 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));
    })
  };
})
  • 0
    Не может ли эта директива также использовать $sce.trustAsHtml ?
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, поэтому то, что вы пытались, представляет собой привязку внутри привязки, которая не работает.

  • 0
    Однако, если я удаляю его, мне ничего не вводят. И документы сильно сбивают с толку, используя один} docs-angularjs-org-dev.appspot.com/api/…
  • 0
    Очень странно. Я только что проверил это, чтобы быть уверенным, и для меня это работало как ожидалось. Я согласен, что один {} немного запутывает в документах, но они предназначены для представления выражения, а не литералов в строке. Я обновил свой ответ с рабочим планом.
Показать ещё 3 комментария
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 и других типов, объявленных здесь

2

У меня была аналогичная проблема. Все еще не удалось получить контент из моих файлов разметки, размещенных на github.

После настройки белого списка (с добавленным доменом github) в $sceDelegateProvider в app.js он работал как шарм.

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

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

1

Строгое контекстное экранирование может быть полностью отключено, что позволяет вам вводить 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, но, как замечает doc:

SCE дает вам много преимуществ по безопасности для небольших накладных расходов на кодирование. Будет гораздо сложнее принять приложение, отключенное SCE, и либо закрепите его самостоятельно или включите SCE на более позднем этапе. Это может сделать смысл отключить SCE для случаев, когда у вас много существующего кода которое было написано до введения SCE, и вы переносите их модуль за раз.

  • 0
    Полезно знать, но, безусловно, с этим нужно обращаться осторожно.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню