【问题标题】:With ng-bind-html-unsafe removed, how do I inject HTML?删除 ng-bind-html-unsafe 后,如何注入 HTML?
【发布时间】:2013-10-25 06:35:17
【问题描述】:

我正在尝试使用 $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

【问题讨论】:

标签: html angularjs


【解决方案1】:

你不需要在 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/…
  • 很奇怪。我刚刚对其进行了测试以确保它按预期工作。我同意单个 { } 在文档中有点令人困惑,但它们是作为表达式的表示,而不是作为字符串中的文字。我已经用一个有效的插件更新了我的答案。
  • 另外,如果您已经在使用 1.2.0,请在此处查看 cmets,因为 ng-bind-html-unsafe 已被删除:docs.angularjs.org/api/ng.directive:ngBindHtml
  • 我使用的是 1.2。 :( Grrr!如何注入不安全的 HTML?没有它我会得到这个错误:errors.angularjs.org/undefined/$sce/unsafe
  • {{}} 运算符导致我的绑定失败问题,感谢您的提示!
【解决方案2】:

您表示您正在使用 Angular 1.2.0...正如其他 cmets 之一所指出的那样,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 中修复了 a bug,这会阻止“观察者”在受信任的 HTML 上正常工作。)

【讨论】:

  • 我尝试使用上述方法,但它破坏了我的代码。似乎您需要在函数定义之前添加 '$scope' - 也许它曾经被“理解”,但不再是。以下应该有效:myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
  • 你可以看看更多关于$sce的信息here只是为了追求好奇心! ;)
  • 请注意,这可能会导致您的代码中出现 XSS 安全问题。请参阅下面建议 ngSanitize 的答案 (stackoverflow.com/a/25679834/22227),以获得更安全的替代解决方案。
  • 为什么这是个坏主意:docs.google.com/presentation/d/…
  • trustAsHtml 言行一致,它信任 any 传入的 html 代码,这可能导致跨站脚本 (XSS) 攻击
【解决方案3】:

您可以创建自己的简单不安全的 html 绑定,当然如果您使用用户输入,则可能存在安全风险。

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

【讨论】:

  • 这个指令不能也使用$sce.trustAsHtml吗?
【解决方案4】:

我也遇到过类似的问题。仍然无法从我托管在 github 上的 markdown 文件中获取内容。

在 app.js 中为 $sceDelegateProvider 设置白名单(添加了 github 域)后,它就像一个魅力。

说明:如果您从不同的 url 加载内容,则使用白名单而不是包装为受信任。

文档: $sceDelegateProviderngInclude(用于获取、编译和包含外部 HTML 片段)

【讨论】:

    【解决方案5】:

    对我来说,最简单、最灵活的解决方案是:

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

    并向您的控制器添加功能:

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

    不要忘记将$sce 添加到控制器的初始化中。

    【讨论】:

    • 让控制器在 $scope 中返回受信任的 html 似乎更直接
    • 这可能会在 $sce 上引发无限循环,请执行以下操作:$scope.trusted = {}; $scope.to_trusted = function(html_code) { return $scope.trusted[html_code] || ($scope.trusted[html_code] = $sce.trustAsHtml(html_code)); };
    • 每个涉及将 HTML 设置为受信任的解决方案都会引入 XSS 漏洞。请参阅下面建议 ngSanitize 的答案 (stackoverflow.com/a/25679834/22227) 以获得更安全的修复。
    【解决方案6】:

    您可以将其转换为简单的过滤器,而不是像 Alex 建议的那样在您的范围内声明一个函数:

    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/

    【讨论】:

    • 我在github 上收集了一些有用的角度工具,如果您不介意,我会将这个过滤器包含在这些工具中。当您信任 html 时,恕我直言,这是最好的解决方案。
    • @Capaj 没问题,但是如果您添加指向此答案的链接,我们将不胜感激。 :-) stackoverflow.com/a/21254635
    • 非常好。这就像嵌套重复的魅力!
    • 这似乎是一个比为每个控制器编码更好的解决方案。只需快速过滤即可完成!我将它与重复表行一起使用,就像馅饼一样简单......&lt;td ng-bind-html="representative.primary | to_trusted"&gt;&lt;/td&gt;
    • angular.module('myApp').filter('trustAsHtml', ['$sce', function($sce) { return $sce.trustAsHtml }]);
    【解决方案7】:
    1. 您需要确保已加载 sanitize.js。例如,从https://ajax.googleapis.com/ajax/libs/angularjs/[LAST_VERSION]/angular-sanitize.min.js 加载它
    2. 您需要在您的app 中包含ngSanitize 模块 例如:var app = angular.module('myApp', ['ngSanitize']);
    3. 你只需要绑定ng-bind-html原来的html内容。无需在控制器中执行任何其他操作。解析和转换由ngBindHtml 指令自动完成。 (阅读How does it work 部分:$sce)。因此,在您的情况下,&lt;div ng-bind-html="preview_data.preview.embed.html"&gt;&lt;/div&gt; 会完成这项工作。

    【讨论】:

    • 这是最安全的选择。它带有更多的依赖关系,但它是关于安全的,所以毫不犹豫!
    • 将其与 ionic 1.0.0-beta.13 一起使用
    • 这不适用于某些标签,例如输入。当然,没有简单的方法可以解决这个问题。真令人沮丧。
    • 最常见和最安全的方式。如果您打算在不同的视图中使用 bind-html,则更喜欢这个。
    【解决方案8】:

    在我看来,最好的解决方案是:

    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% 的时间,它永远有效。

    【讨论】:

    • 您可以使用以下正则表达式进行查找和替换:正则表达式:ng-bind-html-unsafe="((?:(?!").)*)" 替换:ng-绑定-html="($1) | html" 与上述过滤器。
    • 每个涉及将 HTML 设置为受信任的解决方案都会引入 XSS 漏洞。请参阅下面建议 ngSanitize 的答案 (stackoverflow.com/a/25679834/22227) 以获得更安全的修复。
    【解决方案9】:

    可以完全禁用严格的上下文转义,允许您使用ng-html-bind 注入 html。这是一个不安全的选项,但在测试时很有帮助。

    来自AngularJS documentation on $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 之前编写的,您正在迁移它们 一个模块。

    【讨论】:

    • 很高兴知道,但绝对应该小心处理。
    【解决方案10】:

    你可以像这样使用过滤器

    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>
    

    它可用于其他资源类型,例如 iframe 的源链接和声明为here 的其他类型

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多