React中使用dangerouslySetInnerHTML时如何有效防止XSS攻击? 司马怡博 提问于 2026-02-11 10:21:34 阅读 24 安全 我在做一个可以渲染富文本内容的功能,直接用dangerouslySetInnerHTML渲染用户提交的HTML字符串时,发现能被注入恶意脚本。虽然用了htmlspecialchars转义,但页面样式完全乱了: .user-content { font-size: 1.2em; .danger { color: red; } } 尝试过用DOMPurifysanitize,但不确定是否需要结合其他措施。直接转义导致CSS类名也被转义失效了,有没有更稳妥的防护方法? CanvasHTML5XSS防护 我来解答 赞 5 收藏 分享 生成中... 手机扫码查看 复制链接 生成海报 反馈 发表解答 您需要先 登录/注册 才能发表解答 2 条解答 Newb.瑞静 Lv1 用 dangerouslySetInnerHTML 渲染富文本确实是个常见的需求,但安全问题也确实让人头疼。我之前也碰到过类似的情况,最后是用 DOMPurify 解决的。 DOMPurify 是一个专门用来清理 HTML 的库,可以有效防止 XSS 攻击。它会移除所有不安全的标签和属性,同时保留合法的 HTML 和样式。你可以这样用: import DOMPurify from 'dompurify'; function sanitizeHtml(html) { return { __html: DOMPurify.sanitize(html) }; } function UserContent({ content }) { return <div dangerouslySetInnerHTML={sanitizeHtml(content)} />; } 这里的关键点是,DOMPurify.sanitize 会帮你过滤掉像 <script> 这样的危险标签,同时保留像 <p>、<span> 和 CSS 类名这些无害的内容。你提到样式乱了的问题,可能是因为转义的时候把 CSS 类名也转义了,而 DOMPurify 不会有这个问题。 如果你需要支持更复杂的场景,比如允许某些特定的标签或属性,可以通过配置 DOMPurify 来实现。比如这样: const cleanHtml = DOMPurify.sanitize(dirtyHtml, { ALLOWED_TAGS: ['p', 'span', 'strong', 'a'], ALLOWED_ATTR: ['href', 'class'] }); 另外,记得在服务端也做一层防护,别光靠前端处理。虽然前端用 DOMPurify 已经很稳妥了,但多一道防线总是好的。我们团队之前就是因为只依赖前端过滤,结果被绕过了,差点出大事,真是教训深刻啊。 总结一下,推荐用 DOMPurify 来清理用户提交的 HTML,既能防止 XSS 攻击,又能保留合法的样式和结构。如果还有其他特殊需求,可以根据实际情况调整配置。 回复 点赞 2026-02-19 18:26 夏侯金壵 Lv1 直接用 dangerouslySetInnerHTML 渲染用户输入的 HTML 是高危操作,htmlspecialchars 是服务端转义用的,用来处理前端富文本会把标签都变成字符实体,样式当然失效。你看到的问题就是因为整个 HTML 被当成纯文本输出了。 推荐的做法是使用 DOMPurify 进行内容净化,它能自动过滤 script、onerror 等恶意标签和事件属性,同时保留合法的标签和 class 属性。你之前尝试用 DOMPurify 的方向完全正确,不需要再加 htmlspecialchars。 安装: npm install dompurify 在 React 中使用: import DOMPurify from 'dompurify'; function UserContent({ html }) { const clean = DOMPurify.sanitize(html); return <div dangerouslySetInnerHTML={{ __html: clean }} />; } DOMPurify 默认配置已经很安全,支持白名单机制,比如你可以限制只允许 p、div、span、strong 和特定 class: const clean = DOMPurify.sanitize(html, { ALLOWED_TAGS: ['p', 'div', 'span', 'strong'], ADD_ATTR: ['class'] }); 注意:如果后端存储的是原始未转义的 HTML,确保在存储时也做过基本校验,防止“存储型 XSS”。前后端都要有防护,但前端展示一律用 DOMPurify 处理。 总结:别用 htmlspecialchars 处理要渲染成 HTML 的内容,用 DOMPurify 净化后再通过 dangerouslySetInnerHTML 输出,这是目前社区公认最稳妥的方案。 回复 点赞 2 2026-02-11 11:04 加载更多 相关推荐
dangerouslySetInnerHTML渲染富文本确实是个常见的需求,但安全问题也确实让人头疼。我之前也碰到过类似的情况,最后是用DOMPurify解决的。DOMPurify是一个专门用来清理 HTML 的库,可以有效防止 XSS 攻击。它会移除所有不安全的标签和属性,同时保留合法的 HTML 和样式。你可以这样用:这里的关键点是,
DOMPurify.sanitize会帮你过滤掉像<script>这样的危险标签,同时保留像<p>、<span>和 CSS 类名这些无害的内容。你提到样式乱了的问题,可能是因为转义的时候把 CSS 类名也转义了,而DOMPurify不会有这个问题。如果你需要支持更复杂的场景,比如允许某些特定的标签或属性,可以通过配置
DOMPurify来实现。比如这样:另外,记得在服务端也做一层防护,别光靠前端处理。虽然前端用
DOMPurify已经很稳妥了,但多一道防线总是好的。我们团队之前就是因为只依赖前端过滤,结果被绕过了,差点出大事,真是教训深刻啊。总结一下,推荐用
DOMPurify来清理用户提交的 HTML,既能防止 XSS 攻击,又能保留合法的样式和结构。如果还有其他特殊需求,可以根据实际情况调整配置。推荐的做法是使用 DOMPurify 进行内容净化,它能自动过滤 script、onerror 等恶意标签和事件属性,同时保留合法的标签和 class 属性。你之前尝试用 DOMPurify 的方向完全正确,不需要再加 htmlspecialchars。
安装:
在 React 中使用:
DOMPurify 默认配置已经很安全,支持白名单机制,比如你可以限制只允许 p、div、span、strong 和特定 class:
注意:如果后端存储的是原始未转义的 HTML,确保在存储时也做过基本校验,防止“存储型 XSS”。前后端都要有防护,但前端展示一律用 DOMPurify 处理。
总结:别用 htmlspecialchars 处理要渲染成 HTML 的内容,用 DOMPurify 净化后再通过 dangerouslySetInnerHTML 输出,这是目前社区公认最稳妥的方案。