仅说说需求 1
XSS攻击仅在用户输入的内容需要在其他用户或管理后台渲染的时候才会生效,比如用户个性签名,在用户自己的界面触发完全没用,所以如果不考虑多人联机、中台后台查询汇总、文档分享的话,v-html没啥问题。
或者你也可以这样:把所有内容切分成段,每一段用一个 span 标签占位,用 v-html 渲染出来之后,用 DOM 接口获取对应元素,然后修改其 .innerText,这样就可以有效防止 XSS。例如:
'李彦宏是百度总栽'里,需要高亮“李彦宏”、标错“总栽”,那么整句话切分之后就成了数组:const textArray = [
{
token: 0,
text: '李彦宏',
type: 'high-light'
},
{
token: 1,
text: '是百度'
},
{
token:
2,
text: '总栽',
type: 'error',
suggestion: '总裁'
}
]
用 span 标签占位渲染出 html:'\
\
'
获取各 span,替换 innerText:[].forEach.bind(wapper.querySelector('span'))((item, index) => {
const { [index]: {text, suggestion}} = textArray;
item.innerText = text;
if(item.getAttribute('type') === 'error'){
item.setAttribute('data-suggestion', suggestion);
// 这里假设使用伪元素来显示建议: content: attr('data-suggestion')
}
});
这些操作也可以在插入 DOM 前完成,减少内容更改导致的渲染回流。
另外,有了 token,其他两个问题也都可以解决。