前端做XSS输入过滤到底该在哪儿处理?
我最近在用 Vue 写一个评论功能,用户输入的内容会直接渲染到页面上。我知道要防 XSS,但不确定是在输入时就过滤掉危险字符,还是在渲染时转义?试过在提交前用正则替换 script 标签,但好像还是能绕过……
比如下面这段代码,我把用户输入直接绑定到 v-html 里,虽然加了简单过滤,但总觉得不安全:
<template>
<div v-html="sanitizeInput(userComment)"></div>
</template>
<script>
export default {
methods: {
sanitizeInput(str) {
return str.replace(/<scriptb[^<]*(?:(?!</script>)<[^<]*)*</script>/gi, '');
}
}
}
</script>
这样写真的能防住 XSS 吗?还是说应该完全避免用 v-html?
如果非要渲染不可信的HTML内容,建议用成熟的库来做转义。比如 DOMPurify 这个库就挺靠谱,专门处理这种场景,而且浏览器兼容性也不错。
另外提醒一下,在服务器端也要做一次过滤,不能完全依赖前端。毕竟攻击者可以直接绕过前端验证直接发请求。
说实话,能不用 v-html 就别用,很多时候用文本节点或者简单模板就能满足需求。真要展示富文本,也考虑下把编辑和展示分离,用现成的编辑器组件会省心很多。
最后,永远不要相信用户的任何输入,这行代码写了这么多年还是经常踩坑啊。
正确做法:放弃v-html,用正常插值{{ }}渲染内容,Vue默认会转义。如果必须用v-html,上DOMPurify这个库:
别自己写过滤逻辑,正则防XSS就没靠谱过。