当前位置:AngularJS API / ngSanitize / 服务(service) / $sanitize

要学习这个服务,先要了解另一个指令: ng-bing-html。

顾名思义,ng-bind-html和ng-bind的区别就是,ng-bind把值作为字符串,和元素的内容进行绑定,但是ng-bind-html把值作为html,和元素的html进行绑定.相当于jq里面的.text()和.html().

但是,出于安全考虑,如果我们直接使用ng-bind-html是会报错的,ng-bind-html后面的内容必须经过一定的处理.

处理的方式有两种,一种是使用$sce服务,另一种就是使用$sanitize服务。

$sanitize会根绝一个白名单来净化html标签。这样,不安全的内容就不会被返回。 白名单是根据$compileProvideraHrefSanitizationWhitelistimgSrcSanitizationWhitelist函数得到的。


实例

<div ng-controller="ExampleController">
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
<table>
 <tr>
   <td>Directive</td>
   <td>How</td>
   <td>Source</td>
   <td>Rendered</td>
 </tr>
 <tr id="bind-html-with-sanitize">
   <td>ng-bind-html</td>
   <td>Automatically uses $sanitize</td>
   <td><pre><div ng-bind-html="snippet"><br/></div></pre></td>
   <td><div ng-bind-html="snippet"></div></td>
 </tr>
 <tr id="bind-html-with-trust">
   <td>ng-bind-html</td>
   <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
   <td>
   <pre><div ng-bind-html="deliberatelyTrustDangerousSnippet()">
</div></pre>
   </td>
   <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
 </tr>
 <tr id="bind-default">
   <td>ng-bind</td>
   <td>Automatically escapes</td>
   <td><pre><div ng-bind="snippet"><br/></div></pre></td>
   <td><div ng-bind="snippet"></div></td>
 </tr>
</table>
</div>
angular.module('sanitizeExample', ['ngSanitize'])
	.controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
		$scope.snippet =
			'<p style="color:blue">an html\n' +
			'<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
			'snippet</p>';
		$scope.deliberatelyTrustDangerousSnippet = function() {
			return $sce.trustAsHtml($scope.snippet);
		};
	}]);
it('should sanitize the html snippet by default', function() {
  expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).
    toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
});

it('should inline raw snippet if bound to a trusted value', function() {
  expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).
    toBe("<p style=\"color:blue\">an html\n" +
         "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
         "snippet</p>");
});

it('should escape snippet without any filter', function() {
  expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).
    toBe("<p style=\"color:blue\">an html\n" +
         "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
         "snippet</p>");
});

it('should update', function() {
  element(by.model('snippet')).clear();
  element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
  expect(element(by.css('#bind-html-with-sanitize div')).getAttribute('innerHTML')).
    toBe('new <b>text</b>');
  expect(element(by.css('#bind-html-with-trust div')).getAttribute('innerHTML')).toBe(
    'new <b onclick="alert(1)">text</b>');
  expect(element(by.css('#bind-default div')).getAttribute('innerHTML')).toBe(
    "new <b onclick=\"alert(1)\">text</b>");
});

上面的这个例子,表格的第一行,使用$sanitize服务进行过滤。在这里我们给模块添加依赖 'ngSanitize' ,(需要链入angular-sanitize.min.js).然后使用ng-bind-html,$sanitize会自动对myHtml进行净化.

表格第二行,通过$sce.trustAsHtml() 处理以后的返回值.所以它不再经过$sanitize服务的净化.直接作为元素的.html()绑定给元素,所以我们看到myHtml被完整的填充到了div里,保留了所有的属性和事件,这一行的内容不依赖于ngSanitize模块,$sce服务是内置的

表格第三行,不使用ng-bind-html指令.当使用ng-bind指令时,绑定的值就作为字符串填充到元素里。