
一、快速入门
1.1 DOMPurify 概述
在 JavaScript 开发的世界中,安全性是保护应用程序免受潜在威胁和漏洞的至关重要。在 Vue 3 应用中渲染动态 HTML 内容时,安全风险不容忽视。DOMPurify 是一个开源的基于 DOM 的快速 XSS 净化工具,专门用于净化HTML、MathML和SVG,能有效防御跨站脚本攻击(XSS攻击)。它通过解析递归元素节点来净化 HTML,输出安全的 HTML 内容,能够有效抵御防止XSS攻击。
- DOMPurify 在线演示:cure53.de/purify
1.2 DOMPurify 核心思路
DOMPurify 的核心思想是:不要自己写 HTML 解析器,而是让浏览器来解析。
1.3 安装与引入
可以通过 npm 来安装 DOMPurify 库,命令如下:
bash
# 确认安装版本(含嵌套依赖)
npm install dompurify
# 或者
yarn add dompurify
在需要使用 DOMPurify 的文件中导入 DOMPurify 库,代码如下:
javascript
import DOMPurify from 'dompurify';
1.4 基础用法
使用 DOMPurify 库过滤 HTML 非常简单,可以直接调用 DOMPurify.sanitize() 方法,将需要过滤的HTML字符串作为参数传入,然后它就会返回一个消毒过的版本。比如,在表单的提交中,或者需要根据用户改变html内容的时候,净化字符串,放置隐藏恶意脚本。代码示例如下:
javascript
import DOMPurify from 'dompurify';
// 示例:可能不安全的HTML输入
let rawHtml = '<p>Safe content</p><scr' + 'ipt>alert("XSS")</scr' + 'ipt>';
let sanitizedHtml = DOMPurify.sanitize(rawHtml);
console.log('DOMPurify过滤前:', rawHtml)
console.log('DOMPurify过滤后:', DOMPurify.sanitize(html))
在上面的示例中,我们尝试注入一段 JavaScript 代码。然而,DOMPurify 检测到此并删除它,使得输出的 HTML 代码是安全的。
二、DOMPurify 高级配置
DOMPurify 不仅支持简单的清洗操作,它还提供了详细的配置选项,使得开发人员能够通过配置选项自定义净化规则,以满足不同的安全需求。
2.1 白名单过滤
可以定义一个配置对象来指定自定义允许的标签和属性。
javascript
const config = {
// 只允许这些HTML标签
ALLOWED_TAGS: ['p', 'a', 'b', 'i', 'em', 'strong'],
// 只允许这些HTML属性
ALLOWED_ATTR: ['href', 'title', 'target'],
// 允许自定义URI的协议
ALLOWED_URI_REGEXP: /^(https?|ftp):/i
// 禁止的危险属性
FORBID_ATTR: ['onclick', 'onload']
};
const dirtyHtml = '<p>Hello, <a href="https://example.com" target="_blank" οnclick="alert(1)">World</a>!</p>';
const cleanHtml = DOMPurify.sanitize(dirtyHtml, config);
2.2 自定义钩子
DOMPurify 支持在净化流程的不同阶段插入自定义逻辑,实现高度定制化的安全策略,允许我们在净化过程中进行更细粒度的控制。
| 钩子函数 | 简要说明 |
|---|---|
| beforeSanitizeElements | 在清理元素前触发,可用于提前移除某些节点或属性 |
| afterSanitizeElements | 对节点进行基础清理之后触发,常用于处理链接安全、图片防盗链、强制 HTTPS |
| uponSanitizeShadowNode | |
| beforeSanitizeAttributes | |
| afterSanitizeAttributes | 在清理属性后触发 |
| beforeSanitizeShadowDOM | |
| afterSanitizeShadowDOM | |
| uponSanitizeElement | 当遍历到具体的 HTML 元素时触发,可以用来记录日志、监控被拦截的危险标签 |
| uponSanitizeAttribute | 在处理具体属性时触发,常用于校验 URL 协议,防止执行恶意的 JavaScript 代码 |
例如,可以阻止特定的属性:
javascript
DOMPurify.addHook('uponSanitizeAttribute', (node, data) => {
if (data.attrName === 'src' && /javascript:/i.test(data.attrValue)) {
data.keepAttr = false; // 阻止javascript:协议
}
});
三、最佳实践
3.1 查看被移除的内容
在进行安全审计或调试时,可能需要知道 DOMPurify 移除了哪些内容:
javascript
const dirtyInput = '<script>alert("XSS")</script><p>Safe content</p>';
const clean = DOMPurify.sanitize(dirtyInput);
// 查看被移除的节点
console.log(DOMPurify.removed);
请注意,DOMPurify.removed 主要用于调试,不建议在生产环境中依赖它进行业务逻辑判断。
3.2 结合Vue响应式数据
通常,我们还会将 DOMPurify 与 Vue 的响应式系统(如 ref、computed)结合使用:
html
<script setup>
import { ref, computed } from 'vue';
import DOMPurify from 'dompurify';
const userInput = ref('');
const sanitizedInput = computed(() => DOMPurify.sanitize(userInput.value));
</script>
<template>
<textarea v-model="userInput" placeholder="输入内容"></textarea>
<div v-html="sanitizedInput"></div>
</template>
3.3 使用自定义指令
为了更方便地在模板中使用,可以创建一个自定义指令:
javascript
// main.js 或类似文件
import { createApp } from 'vue';
import App from './App.vue';
import DOMPurify from 'dompurify';
const app = createApp(App);
app.directive('safe-html', (el, binding) => {
el.innerHTML = DOMPurify.sanitize(binding.value);
});
app.mount('#app');
在组件中使用自定义指令:
html
<template>
<div v-safe-html="rawHtml"></div>
</template>
四、总结
当今数字时代,安全性在应用程序开发中变得愈发重要。为了确保用户数据的保密性、完整性和可靠性,开发人员需要采取各种措施来应对安全挑战。DOMPurify 是 Vue 3 应用中处理不安全 HTML 并防御 XSS 攻击的强力工具。通过其简单的 API 和灵活的配置,它可以满足多种安全需求。关键在于牢记安全需要多层防御,切勿完全依赖客户端净化。
