Vue中使用v-html时如何避免XSS漏洞?

UX-自娴 阅读 18

在Vue项目里用v-html渲染用户输入的内容时,发现输入的alert(1)居然真的弹窗了。我试过用replace替换尖括号,但复杂HTML结构就乱了,怎么安全地处理用户输入避免XSS?


<template>
  <div v-html="userContent"></div>
</template>
<script>
export default {
  data() {
    return { userContent: '<p>测试内容</p><script>alert(1)</script>' }
  }
}
</script>

现在直接渲染会导致XSS执行,如果用escape转义又会把所有标签转义成文本,用户正常的带格式内容(比如加粗文字)也会失效,该怎么平衡安全和正常HTML展示?

我来解答 赞 3 收藏
二维码
手机扫码查看
2 条解答
IT人淑涵
要解决这个问题,我们得分几步走。第一步是理解为什么会出现XSS漏洞,第二步是如何安全地处理用户输入,最后一步是给出一个完整的解决方案。

先说为什么会有XSS漏洞。当你用v-html渲染内容时,Vue会直接把字符串当作HTML插入到DOM里。如果你的字符串里包含了恶意脚本,比如 <script>alert(1)</script>,浏览器就会执行这段脚本。这就是XSS攻击的核心原理:恶意代码被注入并执行。

接下来我们要解决的是如何在允许用户输入富文本(比如带格式的内容)的同时,防止恶意代码被执行。这里推荐使用一个专门处理HTML安全的库,比如 DOMPurify。这个库的作用是清理掉HTML中可能引发安全问题的部分,同时保留合法的HTML结构。

下面是具体实现步骤:

第一步,安装 DOMPurify。你可以通过npm安装它:
npm install dompurify


第二步,在你的Vue组件中引入并使用 DOMPurify 来清理用户输入的内容。代码可以这样写:

import DOMPurify from 'dompurify';

export default {
data() {
return {
userContent: '<p>测试内容</p><script>alert(1)</script>'
}
},
computed: {
sanitizedContent() {
// 使用 DOMPurify 清理用户输入的内容
return DOMPurify.sanitize(this.userContent);
}
}
}


第三步,在模板中渲染清理后的内容。修改你的模板代码如下:

<template>
<div v-html="sanitizedContent"></div>
</template>


这里的关键点是,我们没有直接渲染 userContent,而是通过计算属性 sanitizedContent 对内容进行了清理。DOMPurify 会移除像 <script> 这样的危险标签,但会保留像 <p><b> 这样的安全标签,从而既保证了安全性,又不会破坏正常的HTML结构。

如果你还需要支持更多的自定义规则,比如只允许某些特定的标签或属性,DOMPurify 也提供了配置选项。比如你可以这样限制只允许 <p><b> 标签:

return DOMPurify.sanitize(this.userContent, {
ALLOWED_TAGS: ['p', 'b']
});


最后提醒一下,不要试图自己写正则表达式去过滤HTML,因为HTML的复杂性远超你的想象,很容易遗漏一些边缘情况,导致安全漏洞。用专业的库是最靠谱的做法。

总结一下,核心思路就是借助 DOMPurify 来清理用户输入的内容,确保恶意代码被移除,同时保留合法的HTML结构。这样既能防止XSS攻击,又能让用户正常使用富文本功能。
点赞
2026-02-18 14:03
 ___玉戈
我之前踩过这个坑,直接用v-html渲染用户输入确实很容易导致XSS漏洞。解决这个问题的关键是既要过滤掉恶意代码,又要保留安全的HTML标签和格式。

推荐用一个专门处理HTML安全的库,比如DOMPurify。这个库能帮你清理掉恶意脚本,同时保留正常的HTML结构。下面是具体做法:

首先安装DOMPurify:
npm install dompurify


然后在你的Vue组件里这样用:
import DOMPurify from 'dompurify'

export default {
data() {
return {
userInput: '<p>测试内容</p><script>alert(1)</script>'
}
},
computed: {
sanitizedContent() {
// 使用DOMPurify清理用户输入
return DOMPurify.sanitize(this.userInput)
}
}
}


模板部分改成:
<template>
<div v-html="sanitizedContent"></div>
</template>


这里我把处理逻辑放到了computed属性里,这样当userInput变化时会自动重新计算。DOMPurify默认会移除所有危险的标签和属性,比如script、onclick这些,但会保留安全的HTML标签。

我之前试过自己写正则去过滤,结果发现总有漏网之鱼,维护起来也很麻烦。后来换了DOMPurify,感觉省心多了。它还支持配置白名单,如果你有特殊需求可以自定义规则,不过大部分情况下默认配置就够用了。

记得在生产环境还是要保持警惕,最好再加上CSP(内容安全策略)做额外防护。毕竟前端的安全防护多一层总比少一层好。
点赞 1
2026-02-16 21:04