sanitize-html简介
一、简介
sanitize-html提供了一个简单的HTML”消毒”工具来处理在Web中不安全的HTML内容,防止注入攻击。
它提供了简单清晰的API,也很适合清理由ckeditor和其他富文本编辑器创建的HTML片段。
sanitize-html是在htmlparser2模块上构建的;可以设置指定允许的标签以及每个标签允许的属性;还可以对href
或src
属性进行验证,确保只包含http
、https
、ftp
、mailto URLs
和相对URL;还支持对iframe标签的src
属性做过滤(过滤主机名)。其中HTML注释不会被保留。
二、安装&使用
1、node
- 安装
npm install sanitize-html
- 使用
var sanitizeHtml = require('sanitize-html');
var dirty = 'some really tacky HTML';
var result = sanitizeHtml(dirty);
2、Browser
- 安装
在github上克隆仓库,然后执行:
npm install
npm run minify
然后在dist
目录中可以找到sanitize-html的压缩版和非压缩版。
也可以用node安装后,在node_modules\sanitize-html\dist
目录中找到对应的文件。
- 使用
在HTML中引入sanitize-html.js
和自己的demo.js
:
<script type="text/javascript" src="sanitize-html.js"></script>
<script type="text/javascript" src="demo.js"></script>
demo.js
:
var html = "<strong>hello world</strong>";
console.log(sanitizeHtml(html));
console.log(sanitizeHtml("<img src='x' onerror=alert('img') />"));
console.log(sanitizeHtml("console.log('hello world')"));
console.log(sanitizeHtml("<script>alert('hello world')</script>"));
输出:
<strong>hello world</strong>
console.log('hello world')
其中输出的第二行和第四行为空行,内容已被忽略。
三、常用配置
部分属性默认配置如下:
{
allowedTags: [ 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
'nl', 'li', 'b', 'i', 'strong', 'em', 'strike', 'abbr', 'code', 'hr', 'br', 'div',
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'iframe' ],
disallowedTagsMode: 'discard',
allowedAttributes: {
a: [ 'href', 'name', 'target' ],
// We don't currently allow img itself by default, but this
// would make sense if we did. You could add srcset here,
// and if you do the URL is checked for safety
img: [ 'src' ]
},
// Lots of these won't come up by default because we don't allow them
selfClosing: [ 'img', 'br', 'hr', 'area', 'base', 'basefont', 'input', 'link', 'meta' ],
// URL schemes we permit
allowedSchemes: [ 'http', 'https', 'ftp', 'mailto' ],
allowedSchemesByTag: {},
allowedSchemesAppliedToAttributes: [ 'href', 'src', 'cite' ],
allowProtocolRelative: true,
enforceHtmlBoundary: false
}
1、自定义允许的标签
- 样例
在默认配置的基础上允许img标签
var options = {
allowedTags: sanitizeHtml.defaults.allowedTags.concat([ 'img' ])
};
var html = "<img src='x' onerror=alert('img') />";
console.log(sanitizeHtml(html, options));
- 输出
<img src="x" />
2、自定义允许的属性
- 样例
允许所有标签使用data-*
和title
属性,允许p标签使用width
属性:
var options = {
allowedAttributes: {
'p' : [ 'width'],
'*' : ['data-*', 'title']
}
};
console.log(sanitizeHtml("<div width='600px' data-id='123'>Good!</div>", options));
console.log(sanitizeHtml("<p title='Hi!' width='200px' height='100px'>Hello World!</p>", options));
- 输出
<div data-id="123">Good!</div>
<p title="Hi!" width="200px">Hello World!</p>
在默认配置上增加允许的属性:
var options = {
allowedAttributes: _.extend({}, sanitizeHtml.defaults.allowedAttributes, {'*': ["style"]})
}
3、允许某些属性的特定值
- 样例
允许input标签以及type属性和class属性,但type属性只能是text、password、button其中之一,class属性只能从one、two、three中取值,允许多选:
var options = {
allowedTags: sanitizeHtml.defaults.allowedTags.concat([ 'input' ]),
allowedAttributes: {
'input':[
{
'name': 'type',
'values': ['text', 'password', 'button']
},
{
'name': 'class',
'multiple': true,
'values': ['one', 'two', 'three']
}
]
}
};
console.log(sanitizeHtml("<input type='password' class='one three'/>", options));
console.log(sanitizeHtml("<input type='text' class='xxx'/>", options));
console.log(sanitizeHtml("<input type='submit' class='two'/>", options));
- 输出
<input type="password" class="one three" />
<input type="text" />
<input type class="two" />
4、允许所有标签和属性
- 样例
var options = {
allowedTags: false,
allowedAttributes: false
};
console.log(sanitizeHtml("<h1 class='mystyle'>Hello World!</h1>", options));
console.log(sanitizeHtml("<img src='x' onerror=alert('img') />", options));
- 输出
<h1 class="mystyle">Hello World!</h1>
<img src="x" onerror="alert('img')" />
5、不允许任何标签或属性
- 样例
var options = {
allowedTags: [],
allowedAttributes: {}
};
console.log(sanitizeHtml("<a href='go'>Go to the future</a>"));
console.log(sanitizeHtml("<h1 class='mystyle'>Hello World!</h1>", options));
console.log(sanitizeHtml("<img src='x' onerror=alert('img') />", options));
- 输出
<a href="go">Go to the future</a>
Hello World!
6、对不允许标签的处理
-
配置
对不允许标签的处理可以通过属性
disallowedTagsMode
控制,可选值如下:-
discard
默认值,将不允许的标签丢弃
-
escape
将不允许的标签转义
-
recursiveEscape
同escape,并将所有子标签应用相同的处理方式
-
-
样例
console.log(sanitizeHtml("<h1 class='mystyle'>Hello World!</h1>"));
console.log(sanitizeHtml("<img src='x' onerror=alert('img') />"));
var options = {
disallowedTagsMode: 'escape'
};
console.log(sanitizeHtml("<h1 class='mystyle'>Hello World!</h1>", options));
console.log(sanitizeHtml("<img src='x' onerror=alert('img') />", options));
- 输出
Hello World!
<h1>Hello World!</h1>
<img src="x" />
7、标签或属性的转变(transformations)
sanitize-html支持将某种标签转换为另一种标签以及添加或修改属性:
- 样例一
将所有的ol标签转为ul:
var options = {
transformTags: {
'ol': 'ul',
'h3': 'p'
}
};
var html = '<ol><li>item 1</li><li>item 2</li></ol>';
console.log(sanitizeHtml(html, options));
console.log(sanitizeHtml("<h3>Hello World!</h3>", options));
输出:
<ul><li>item 1</li><li>item 2</li></ul>
<p>Hello World!</p>
- 样例二
可以使用simpleTransform方法简单的更改标签或添加属性(其中shouldMerge表示属性是否合并,默认为true):
simpleTransform(newTag, newAttributes, shouldMerge)
将ol标签转换为ul,并将class属性设置为bar:
var options = {
allowedAttributes: {
'*' : ['class']
},
transformTags:{
'ol': sanitizeHtml.simpleTransform('ul', {class: 'bar'})
}
};
var html = '<ol class="foo"><li>item 1</li><li>item 2</li></ol>';
console.log(sanitizeHtml(html, options));
输出:
<ul class="bar"><li>item 1</li><li>item 2</li></ul>
- 样例三
使用自定义处理函数,实现效果同上:
var options = {
allowedAttributes: {
'*' : ['class']
},
transformTags:{
'ol': function(tagName, attribs){
//My own custom magic goes here
return {
tagName: 'ul',
attribs: {
class: 'bar'
}
};
}
}
};
var html = '<ol class="foo"><li>item 1</li><li>item 2</li></ol>';
console.log(sanitizeHtml(html, options));
输出:
<ul class="bar"><li>item 1</li><li>item 2</li></ul>
- 样例四
添加或修改标签的文本内容:
var options = {
allowedAttributes: {
'a': ['href'],
'*': ['class']
},
transformTags:{
'a': function(tagName, attribs){
return {
tagName: tagName,
text: 'Go to the future',
attribs: attribs
};
},
'p': function(tagName, attribs){
return {
tagName: tagName,
text: 'Hello World!',
attribs: {
class: 'foo'
}
};
}
}
};
console.log(sanitizeHtml('<a href="http://feature.com"></a>', options));
console.log(sanitizeHtml('<p></p>', options));
输出:
<a href="http://feature.com">Go to the future</a>
<p class="foo">Hello World!</p>