使用ng-bind-html和$sce.trustAsHtml显示有html符号的内容
angularJS在进行数据绑定时默认是会以文本的形式输出,也就是对你数据中的html标签不进行转义照单全收,这样提高了安全性,防止了html标签中的注入攻击,但有些时候还是需要的,特别是从数据库读取带格式的文本时,无法正常的显示在页面中。
而要对html进行转义,则要在数据绑定的html标签中使用ng-bind-html属性,该属性依赖与$sanitize,也就是需要引入angular-sanitize.js文件,并在module定义时注入该服务ngSanitize。比如:
html:
<span ng-controller="myCtr" ng-bind-html = "htmlStr"></span> javascript: function myCtr($scope){ $scope.htmlStr = ‘<p style="color:red;font-size=18px;"></p>‘; };
如此则可以实现html转义,但有个问题就是style这种标签会被angularJS认为是不安全的所以统统自动过滤掉,而为了保留这些就需要开启非安全模式。可以通过angular自带的$sce服务解决。$sce是angularJS自带的安全处理模块,$sce.trustAsHtml(input)方法便是将数据内容以html的形式进行解析并返回。例如:
<div ng-repeat="article in articles"> <div class="panel-heading"> <h4><b>{{article.title}}</b></h4> </div> <div class="panel-body"> <article id="word-display" ng-bind-html="article.content | trustHtml"> </article> </div> </div>
javascript:
success(function (data) { $scope.articles = data; }); myApp.filter(‘trustHtml‘, function ($sce) { return function (input) { return $sce.trustAsHtml(input); } });
还可以使用$sanitize服务,$sanitize会根绝一个白名单来净化html标签。这样,不安全的内容就不会被返回. 白名单是根据$compileProvider的aHrefSanitizationWhitelist和imgSrcSanitizationWhitelist函数得到的.
贴一段代码:
<!DOCTYPE html> <html ng-app="myApp"> <head> <title></title> <meta charset="utf-8"> <script src="../angular-1.3.2.js"></script> <script src="angular-sanitize.min.js"></script> <script src="script.js"></script> <link type="text/css" href="../bootstrap.css" rel="stylesheet" /> </head> <body> <div class="container"> <table class="table table-bordered" ng-controller="ctrl"> <caption>通过ngSanitize模块的$sanitize服务解析html</caption> <thead> <tr> <th>使用的指令</th> <th>格式化方法</th> <th>指令的写法</th> <th>解析结果</th> </tr> </thead> <tbody> <tr> <td>ng-bind-html</td> <td>使用内置的$sanitize <br/>(不需要出现在js里,只要模型添加了ngSanitize模块, <br/>然后使用ng-bind-html,它的值就自动通过$sanitize编译)</td> <td><pre><div ng-bind-html="myHtml"><br></div></pre></td> <td><div ng-bind-html="myHtml"></div></td> </tr> <tr> <td>ng-bind-html</td> <td>使用$sce的trustAsHtml方法编译<br/>(以后会细讲$sce服务,这里不是重点)</td> <td><pre><div ng-bind-html="trustHtml"><br></div></pre></td> <td><div ng-bind-html="trustHtml"></div></td> </tr> <tr> <td>ng-bind</td> <td>不编译</td> <td><pre><div ng-bind="myHtml"><br></div></pre></td> <td><div ng-bind="myHtml"></div></td> </tr> </tbody> </table> <a class="btn btn-default" href="http://plnkr.co/edit/3FBasliZTRjKs3jwTpoR?p=preview" role="button">plunker</a> </div> </body> </html>
JS部分:
var app =angular.module(‘myApp‘,[‘ngSanitize‘]); app.controller(‘ctrl‘,function($scope,$sce){ $scope.myHtml = ‘<p style="color:blue">an html\n‘ + ‘<em onclick="this.textContent=\‘code_bunny\‘">click here</em>\n‘ + ‘snippet</p>‘; $scope.trustHtml = $sce.trustAsHtml($scope.myHtml) });
对比一下这三种情况的结果:
具体的结果可以看: http://plnkr.co/edit/3FBasliZTRjKs3jwTpoR?p=preview
ng-bind-html如果使用内置的 $sanitize服务,那么$sanitize会自动对myHtml进行净化.$sanitize会把标签的属性都移除,以及绑定在元素上的事件.仅保留了标签和内容.
ng-bind-html如果 通过$sce.trustAsHtml()处理以后的返回值,它不再经过$sanitize服务的净化.直接作为元素的.html()绑定给元素,保留所有的属性和事件,这一行的内容不依赖于ngSanitize模块,$sce服务是内置的.
当使用ng-bind指令时,绑定的值就作为字符串填充到元素里
使用ng-bind-html容易引起XSS(脚本注入攻击),这一点会在后面介绍。