1. ホーム
  2. angular

AngularでHTMLテキストを動的に結合する

2022-02-18 17:57:09

AngularJSの出力変数は{を使用します。 <未定義 {Webページにクライアント側で実行可能なコードを注入し、ブラウザで正常に実行させることでXSSスクリプトインジェクション攻撃を防ぐことができます。有効なXSS攻撃が形成され、攻撃が成功すると、ユーザーに関する何らかの機密情報の取得、ユーザー体験の変更、不正行為の誘発などの可能性があります。

AngularJS は ng-bind-html ディレクティブで HTML テキストを動的にバインドしますが、angular はデフォルトではバインドされた HTML テキストを信頼しません。バインドされた HTML テキストについては $sce.trustAsHtml() メソッドを使用して、angular にそれが信頼できる HTML テキストであると伝える必要があり、さもなければ $sce: unsafe exception エラーを報告します。

単純なHTMLテキストをバインドする方法は次のとおりです。

1. angular-sanitizeモジュールの導入

var demo = angular.module('demoApp', [
    'ngSanitize'
  ])

2. コントローラ

demo.controller('DemoCtrl', ['$scope', 'DemoService', function ($scope, DemoService) {
	$scope.content = '<p> This is a piece of HTML text</p>';
}

3. 表示

<section ng-controller="DemoCtrl">
	<div ng-bind-html="content | htmlTrusted"></div>
</section>

4. htmlTrustedというフィルター、$sceはangularJS独自のセキュリティモジュール$sce、trustAsHtmlメソッドはデータ内容をhtmlとしてパースして返すというものである

demo.filter('htmlTrusted', function ($sce) {
    return function (html) {
      return $sce.trustAsHtml(html)
    }
  });

単純なHTMLテキストであれば、これで解決です。ngBindHhtmlは双方向バインディングのための$scopeと関連付けられず、ngClick、ngHref、ngSHow、ngHideディレクティブなどのアンギュラーがHTML内に存在する場合、それらはコンパイルされず、これらのボタンをクリックしても、何も起きずバインドされた式も更新されないでしょう。

angularのすべてのディレクティブを有効にするにはコンパイルする必要があります。ほとんどの場合、コンパイルはangularの起動時に自動的にコンパイルされますが、もし動的に追加されるテンプレートのためであれば、手動でコンパイルする必要があり、angularの$compileサービスを使ってこの機能を実現することが可能です。

<div html-dynamic="content">
  demo.directive('htmlDynamic', function ($compile) {
    return {
      restrict: 'A',
      replace: true,
      link: function (scope, ele, attrs) {
        scope.$watch('isDomComplete', function (val) {
          if (val) {
            scope.$watch(attrs.htmlDynamic, function (html) {
              ele.html(html);
              $compile(ele.contents())(scope);
            });
          }
        });
      }
    };
  });

  demo.directive('htmlDynamic', function ($compile) {
    return {
      restrict: 'A',
      replace: true,
      link: function (scope, ele, attrs) {
        scope.$watch('isDomComplete', function (val) {
          if (val) {
            scope.$watch(attrs.htmlDynamic, function (html) {
              ele.html(html);
              $compile(ele.contents())(scope);
            });
          }
        });
      }
    };
  });

html-dynamic ディレクティブは、バインドされた属性 html の値が変化するのを待ち、 $compile サービスを使用して動的に html を現在のスコープに渡し、 html の内容が存在する場合には現在の DOM ノードを置き換えるために作成されています。こうすることで、HTMLフラグメント内の式やディレクティブが有効になります。この記事がAngularJSを理解する上でお役に立てれば幸いです。