在使用富文本的时候是很容易出现xss问题的
如果你还不知道什么是xss攻击,那么可以先去了解一下前置知识:什么是xss?
在富文本中防止xss攻击无非是两种方法:
- 黑名单过滤
const xssFilter = (html)=> {
if(!html) return '';
//将script标签过滤
html = html.replace(/<\s*\/?script\s*>/,'');
//过滤html标签中存在的javascript所执行的内容
html = html.replace(/javascript:[^'"]*/g,'');
//过滤html标签中所执行的脚本
html = html.replace(/onerror\s*=\s*['"]?[^'"]*['"]?/g,'');
return html;
}
但是黑名单有一个明显的弊端:在html中有很多标签和事件,要全部过滤掉风险点的确是个大问题,所以一般主流的解决办法是使用白名单
- 白名单过滤
首先需要用到cheerio,它可以将html字符串解析成类似jquery对象,api也与jquery基本一致。
const xssFilter = (html)=>{
if(!html) return '';
const cheerio = require('cheerio');
let $ = cheerio.load(html);
//白名单 key为白名单标签 value为白名单标签的属性
const whiteList = {
'img':['src'],
'font':['color','size'],
'a':['href']
}
$('*').each((index,el)=>{
//过滤标签
if(!whiteList[el.name]){
$(el).remove();
return;
}
//过滤属性
for(let attr in el.attribs){
if(!whiteList[el.name].includes(attr)){
//cheerio如果删除标签中的属性,就将该属性设为null;
$(el).attr(attr,null);
}
}
})
return $.html();
}
但是其实这种需求是很常见的,这里只是列举了实现的原理,在实际开发中个人推荐使用 js-xss
我们可以使用js-xss来改进一下我们的代码
const xssFilter = ()=>{
if(!html) return '';
const xss = require('xss');
const ret = xss(html,{
whiteList:{
img:['src'],
a:['href'],
font:['color','size'],
},
onIgnoreTag(){
return '';
}
});
return ret;
}