前端如何防止XSS攻击?我用了转义还是被绕过了?

丽苹 Dev 阅读 79

最近在做用户评论功能,后端返回的评论内容里可能包含用户输入的HTML,我用DOMPurify.sanitize()处理了,但测试时发现还是能插入脚本,是不是我用法不对?

比如下面这段代码,我以为会被过滤掉,结果居然执行了:

const dirty = '<img src=x onerror=alert(1)>';
const clean = DOMPurify.sanitize(dirty);
document.getElementById('comment').innerHTML = clean;

我查了文档说默认配置应该能防XSS,但实际在Chrome里弹窗了。是不是还要加什么配置?或者我该换别的方案?

我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
UX-亚捷
UX-亚捷 Lv1
DOMPurify 默认配置下确实能防止大部分 XSS 攻击,但有时候确实需要根据具体场景调整配置。你遇到的问题可能是由于默认配置没有启用所有必要的过滤规则。你可以尝试优化一下 DOMPurify 的配置,确保启用了对事件处理器的过滤。试试这样:

const dirty = '<img src=x onerror=alert(1)>';
const clean = DOMPurify.sanitize(dirty, { ADD_ATTR: ['src'], FORBID_TAGS: ['img'], FORBID_ATTR: ['onerror'] });
document.getElementById('comment').innerHTML = clean;


这里我禁用了 img 标签和 onerror 属性作为示例,你可能需要根据实际情况调整这些配置。不过,最安全的做法是尽量避免使用 innerHTML 插入不可信的内容。如果可能的话,考虑使用 textContent 或者创建元素节点的方式来插入内容,这样可以完全避免 XSS 风险。

另外,虽然 DOMPurify 很强大,但安全这块儿没有绝对的银弹,最好还是多一层防御,比如后端也要做相应的过滤和校验。
点赞
2026-03-20 22:21
Newb.小青
你的问题在于输入的时机不对。

你传入DOMPurify的是已经HTML实体编码过的字符串 <img src=x onerror=alert(1)>,DOMPurify拿它当普通文本处理,根本不会识别成HTML标签。然后你通过innerHTML赋值时,浏览器自动解码,就成了可执行的

所以流程反了:要么后端返回原始HTML你自己sanitize,要么前端收到编码后的字符串先解码再sanitize。

最简单的修复:

// 先解码,再sanitize
const dirty = '<img src=x onerror=alert(1)>';
const decoded = new DOMParser().parseFromString(dirty, 'text/html').documentElement.textContent;
const clean = DOMPurify.sanitize(decoded);
document.getElementById('comment').innerHTML = clean;


或者更直接的方式:让后端别返回实体编码的内容,返回原始HTML字符串,然后直接用DOMPurify处理。

// 后端返回原始HTML时直接用
const rawHtml = '';
const clean = DOMPurify.sanitize(rawHtml);
document.getElementById('comment').innerHTML = clean;


另外提醒一下,如果你用的是React或者Vue这些框架,它们的默认渲染机制本身就能避免这类问题,除非你用 dangerouslySetInnerHTML 或者 v-html。
点赞
2026-03-17 15:23