react安全渲染 HTML 字符串格式

1,500 阅读1分钟

dangerouslySetInnerHTML 是 React 为浏览器 DOM 提供 innerHTML 的替换方案,用来在 JSX 中渲染 HTML 格式的字符串内容

通常来讲,使用代码直接设置 HTML 存在风险,因为很容易无意中使用户暴露于跨站脚本(XSS)的攻击

HTML 5 中规定:不执行由 innerHTML 插入的 <script> 标签。

但是,有很多不依赖 script 标签去执行 JavaScript 的方式。比如,以下代码会执行 alert 弹窗,造成安全问题:

// 注意:此处图片的 onerror 属性的代码,还是会被执行,不仅影响了用户体验,还会存在 XSS 攻击问题
<div
  className="content-html dg-html"
  dangerouslySetInnerHTML={{
    __html: "<img src='x' onerror='alert(1)'>",
  }}
></div>

因此,为了安全可以通过类似于 dompurify 包,来对 HTML 字符串内容进行“消毒”:

import DOMPurify from 'dompurify';


// 比如,将 '<div><script>alert(111)</script></div>' 转化为: '<div></div>'
// 比如,将 '<img src="x" onerror="alert(1)">' 转化为:'<img src="x" />'
const clean = DOMPurify.sanitize(dirty);

步骤

  1. 安装 dompurify 和 类型声明文件:yarn add dompurify yarn add -D @types/dompurify
  2. 导入 dompurify 包
  3. 通过 dangerouslySetInnerHTML 来展示消毒后的 HTML 内容

核心代码

import DOMPurify from 'dompurify';


<div
  className="content-html dg-html"
  dangerouslySetInnerHTML={{
    __html: DOMPurify.sanitize(content),
  }}
/>;