【问题标题】:Escape HTML text in an AngularJS directive在 AngularJS 指令中转义 HTML 文本
【发布时间】:2013-01-05 22:08:49
【问题描述】:

是否有一个 Angular JS 命令可以对文本进行 HTML 转义?我正在处理一个自定义指令,并且需要转义它生成的一些输出。

AngularJS sanitzer 在内部使用 encodeEntities 函数,但不公开它。我知道我可以复制该功能,但似乎应该有一个标准的方法来做到这一点。


用例:我有一个自定义指令可以进行语言本地化。该指令使用数据文件中的键查找来查找语言文本。在某些情况下,允许此文本包含 HTML,和/或指令生成 HTML 以改进生成的视觉格式。此外,该指令将 Angular 表达式作为参数,并将它们用作字符串中标记的替换。我需要对这些参数进行编码,因为它们可能不是 HTML 安全的。

指令作为属性调用,例如i18n-html='welcome_text_html,1+1,user.name'。然后该指令按照描述格式化字符串并使用element.html 更新 DOM 节点。

【问题讨论】:

  • 默认情况下,数据绑定时会自动转义。你能提供更多关于你的用例的信息吗?
  • 这回答了您的问题还是您需要更多信息?
  • 乔希,你知道在文档中的哪个地方声明绑定的数据被转义了

标签: angularjs


【解决方案1】:

在您在 Angular 应用程序中使用的 HTML 模板文件中使用 [innerHtml] 速记标记。

下面显示的示例转义 wordpress 在从我的 WP API 检索的 post_content 上生成的 HTML,因此 html 标记不会显示在浏览器中:

<div [innerHtml]="post.post_content" *ngIf="post && post.post_content"></div>

希望这会有所帮助。

【讨论】:

  • 问题是关于 AngularJS,而不是 Angular。
【解决方案2】:

这不是直接的解决方案,但如果您深入研究 angular-sanitize 代码,您可以找到函数 encodeEntities。这很好,但很私密。寻找它的用法你会去htmlSanitizeWriter,然后去sanitizeText。 它仍然是私有的,但用于公共过滤器linky

您可以显式使用linky 并希望找不到任何链接,或者在您的服务中重新实现sanitizeTextencodeEntities

【讨论】:

    【解决方案3】:

    你可以像这样实现过滤器:

    app.filter('escape', escape);
    
     function escape() {
        return function (html) {
          return angular.element('<pre/>').text(html).html();
        };
      }
    

    【讨论】:

    • 使用浏览器的内置转义效果很好。
    • ...并换行 :(
    • 这是一个安全隐患 - 将 html 视为 &lt;img src="dummy" onerror="alert('xss')"&gt;。即使元素从未插入到文档中,这也会运行 JavaScript 代码。
    • 好的,那为什么我把它放到控制台时看不到警报?例如angular.element('
      ').text("").html();你知道为什么?因为方法 .text() 做得很好
    • @ruX,标签
       用于保存新行!
    【解决方案4】:

    这个答案来自 @mb21 的。唯一改变的是使用$sce。所以你可以在ng-bind-html中使用这个过滤器,而不触发Error: $sce:unsafe

    angular
      .module('yourModule', [
        'ngSanitize'
      ])
      .filter('escapeHtml', function ($sce) {
        // Modified by Rockallite: Add $sce.trustAsHtml() to mute "Error: $sce:unsafe"
        // http://stackoverflow.com/a/32835368/2293304
        // http://stackoverflow.com/a/28537958/2293304
        // https://github.com/janl/mustache.js/blob/master/mustache.js#L82
        var entityMap = {
            "&": "&amp;",
            "<": "&lt;",
            ">": "&gt;",
            '"': '&quot;',
            "'": '&#39;',
            "/": '&#x2F;'
        };
    
        return function(str) {
          return $sce.trustAsHtml(String(str).replace(/[&<>"'\/]/g, function (s) {
              return entityMap[s];
          }));
        }
      });
    

    【讨论】:

      【解决方案5】:

      转义 HTML 有两个不同的问题。第一个问题是需要对实体进行编码,第二个问题是需要信任结果,以便将数据用作 html 绑定。将以下代码添加到您的控制器可以使用 $sce 服务为这两个问题提供解决方案。

      CoffeeScript 解决方案:

      MyApp.controller('MyController', ['$scope','$sce',($scope,$sce) ->
      
        ###
        ...
        ###
      
        $scope.html5Entities = (value) ->
          value.replace(/[\u00A0-\u9999<>\&\'\"]/gim, (i) ->
            '&#' + i.charCodeAt(0) + ';'
          )
      
        $scope.trustAsHtml = (value) ->
          $sce.trustAsHtml(value)
      
        ###
        ...
        ###
      
      ])    
      


      Javascript 解决方案:

      MyApp.controller('MyController', ['$scope','$sce', function($scope,$sce) {
      
        /* ... */
      
        $scope.html5Entities = function(value) {
          return value.replace(/[\u00A0-\u9999<>\&\'\"]/gim, function(i) {
                return '&#' + i.charCodeAt(0) + ';'
              })
        };
      
        $scope.trustAsHtml = function(value) {
           return $sce.trustAsHtml(value);
        };
      
        /* ... */
      
      }]);
      


      第一个函数 html5Entities 执行实际的实体编码,而第二个函数 trustAsHtml 将字符串标记为在 Angular 中用于 HTML 绑定是安全的。这两个版本都要求您的控制器中包含 $sce 服务。

      示例用法:

      <div ng-bind-html="trustAsHtml((html5Entities(product.title) | highlight: $select.search))"></div>
      

      查看相关问题:

      【讨论】:

      • 谢谢,html5Entities 过滤器代码正是我搜索到的。
      【解决方案6】:

      这个答案是关于转义,而不是清理 HTML。有两种方法:

      1. 正如@maniekq 所提到的,如果您可以在 DOM 上工作,请执行以下操作:

        element.text( scope.myValue );
        
      2. 来自this answer,您可以使用此code from mustache.js 和例如创建一个角度过滤器:

        angular.module('myModule').filter('escapeHtml', function () {
        
            var entityMap = {
                "&": "&amp;",
                "<": "&lt;",
                ">": "&gt;",
                '"': '&quot;',
                "'": '&#39;',
                "/": '&#x2F;'
            };
        
            return function(str) {
                return String(str).replace(/[&<>"'\/]/g, function (s) {
                    return entityMap[s];
                });
            }
        });
        

      【讨论】:

      • 嗯。您为在 HTML 中使用而转义的值将用作文本内容或属性值,对吗?而且这些情况都不需要转义正斜杠?那么为什么正斜杠会在这里转义呢?
      • 但是,如果要在ng-bind-html 中使用此过滤器,则必须将返回值包装在$sce.trustAsHtml() 中。否则,Error: $sce:unsafe 将被提升。
      【解决方案7】:

      清理是一回事,但为了显示所有字符而不是“执行”HTML 代码,我使用了“文本”函数来设置值。

      在你的指令中,设置值,而不是写:

      element.html( scope.myValue );
      

      写:

      element.text( scope.myValue );
      

      【讨论】:

      • 不,这将转义所有文本。我的指令是组装各种位并自行进行 HTML 格式化。我必须使用html 命令来设置输出。我一直在寻找一种方法来自行转义这些位。
      【解决方案8】:

      你可以使用ngSanitize中的encodeEntities()函数来转义&等

      【讨论】:

      【解决方案9】:

      有两种方法可以在 AngularJS 中进行 HTML 清理。第一个是使用 ngBindHtml 指令,第二个是使用 $sanitize 服务。

      function MyCtrl ( $scope, $sanitize ) {
        $scope.rawHtml = "<div><script></script></div>";
        $scope.sanitizedHmtl = $sanitize( $scope.rawHtml );
      }
      

      那么这两者在功能上是等价的:

      <div ng-bind-html="rawHtml"></div>
      <div ng-bind-html-unsafe="sanitizedHtml"></div>
      

      如果在指令中使用,就像您的问题一样,您可以简单地插入经过清理的 HTML:

      element.html( scope.sanitizedHtml );
      

      但在大多数情况下,在编写指令时,您会在模板中使用它并使用 ngBindHtml,如上所述。但它适用于极端情况。

      【讨论】:

      • 我只是在寻找一个标准函数来转义 HTML。标准的自动转义机制都不能达到我的目的。
      • $sanitize 接受一个字符串并返回一个经过清理的字符串。它没有什么是你需要的?
      • 消毒不等于逃避。 Escpaing 正在进行转换,例如 &amp;lt;&amp;lt;
      • @edA $sanitize 据我所知确实是这样做的,看看 AngularJS 的演示
      • @BasGoossen 不一样,因为它完全删除了&lt;script&gt;alert('pwned')&lt;/script&gt; 之类的东西,而不是将&amp;lt;&amp;gt; 之类的标记编码为&amp;lt; &amp;gt;。该文档实际上声明“通过将 HTML 解析为令牌来清理输入。然后将所有安全令牌(来自受信任的 URI 列表)序列化回正确转义的 HTML 字符串。” docs.angularjs.org/api/ngSanitize/service/$sanitize
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多