删除ng-bind-html-unsafe后,如何注入HTML?


265

我正在尝试使用$sanitizeprovider和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+,有一个简单的解决方案,请参阅发布信息
John Henckel

Answers:


123
  1. 您需要确保已加载sanitize.js。例如,从https://ajax.googleapis.com/ajax/libs/angularjs/[LAST_VERSION]/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 2014年

3
这不适用于某些标签,例如输入。当然,没有简单的方法可以解决此问题。真令人沮丧。
Casey 2014年

最普通和安全的方式。如果您打算在不同的视图中使用bind-html,请首选此方法。
eduardobursa 2015年

350

您可以将其转换为简单的过滤器,而不是像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/


3
我在github上有少量有用的角度工具,如果您不介意,我会将这些过滤器包括在这些工具中。当您信任html时,这是恕我直言的最佳解决方案。
Capaj 2014年

@Capaj没问题,但是如果您添加此答案的链接,将不胜感激。:-) stackoverflow.com/a/21254635
Leeroy Brun 2014年

非常好。这就像嵌套重复中的魅力一样!
Jelle Verzijden

这似乎比对每个控制器进行编码要好得多。只需快速过滤即可完成!我有重复表中的行,就这么简单馅饼用它.... <td ng-bind-html="representative.primary | to_trusted"></td>
菲尔·尼古拉斯

2
angular.module('myApp')。filter('trustAsHtml',['$ sce',function($ sce){return $ sce.trustAsHtml}]));
bradw2k 2015年

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
我尝试使用上面的方法,但它破坏了我的代码。似乎您需要在函数定义之前添加“ $ scope”-也许它一次被“理解”了,但是不再。以下应该工作:myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
Dexygen,2014年

4
您可以在此处查找有关$ sce的更多信息,以求好奇!;)
Genuinefafa 2014年

5
请注意,这可能会在您的代码中引起XSS安全问题。请参阅ngSanitize下面建议的答案(stackoverflow.com/a/25679834/22227),以获得更安全的替代方法。
马丁·普罗布斯特

为什么这是一个坏主意:docs.google.com/presentation/d/...
user857990

trustAsHtml做到了所说的话,它信任任何传入的html代码,这可能会导致跨站点脚本(XSS)攻击
Aleksey Solovey

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到控制器的初始化中。


似乎更直接的方法是让控制器返回$ scope中的受信任的html
meffect 2014年

1
这可能会在$ sce上引发无限循环,执行类似以下操作:$ scope.trusted = {}; $ scope.to_trusted =函数(html_code){返回$ scope.trusted [html_code] || ($ scope.trusted [html_code] = $ sce.trustAsHtml(html_code)); };
AO_

1
每个涉及祝福HTML被信任的解决方案都会引入XSS漏洞。请参阅下面的建议ngSanitize的答案(stackoverflow.com/a/25679834/22227),以获得更安全的修复程序。
Michele Spagnuolo

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-htmltrustAsHtml作为其功能的一部分-对我来说似乎有点愚蠢,因为它没有

无论如何-这就是我的方式-67%的时间都可以正常工作。


您可以使用以下正则表达式进行查找和替换:regex:ng-bind-html-unsafe =“((?:( ?!”)。)*)“替换:ng-bind-html =”($ 1) | HTML”与上述滤膜。
乔治Donev

2
每个涉及祝福HTML被信任的解决方案都会引入XSS漏洞。请参阅下面的建议ngSanitize的答案(stackoverflow.com/a/25679834/22227),以获得更安全的修复程序。
Michele Spagnuolo

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吗?
2014年

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
ksimons

2
我正在使用1.2。!?::(哎呀怎么能注入不安全HTML我得到这个错误没有它errors.angularjs.org/undefined/$sce/unsafe
metalaureate

{{}}操作是引起了我的问题与结合失败了,谢谢你的提示!
Campbeln 2014年

2

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

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

说明:如果您从其他网址加载内容,请使用白名单而不是包装为受信任的内容。

文档: $ sceDelegateProviderngInclude(用于获取,编译和包括外部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);
});

将上面的config部分附加到您的应用程序后,您就可以将html注入ng-html-bind,但作为文档注释:

SCE为您提供了许多安全优势,而编码开销却很少。采取禁用SCE的应用程序并自行保护它或在以后的阶段启用SCE会更加困难。对于以下情况,禁用SCE可能是有意义的:在这种情况下,您在引入SCE之前已经编写了很多现有代码,并且一次要迁移它们一个模块。


很高兴知道,但是绝对应该小心处理。
iconoclast

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>

它可以用于其他资源类型,例如iframe的源链接以及此处声明的其他类型

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.