HTML字符串转换为React元素实现
HTML字符串安全转换为React元素的实现
一、背景介绍
- 介绍HTML字符串在Web开发中的常见场景。
- 说明React中直接使用HTML字符串的局限性。
- 提出将HTML字符串转换为React元素的需求。
二、首先必备的两个npm库:'html-react-parser'和'dompurify' 导入:
pnpm install html-react-parser dompurify
三、介绍
import parser from 'html-react-parser';
这行代码的作用是从 html-react-parser
库中导入 parser
函数。这个库的主要功能是将 HTML 字符串转换为 React 元素(React nodes),方便在 React 应用中动态渲染 HTML 内容。
具体作用:
-
将 HTML 字符串转换为 React 元素
-
如果你从 API、数据库或其他地方获取了一段 HTML 字符串(比如
<div>Hello <strong>World</strong></div>
),你可以用parser
将其转换成 React 可以渲染的 JSX 结构。
-
-
替代
dangerouslySetInnerHTML
-
在 React 中,直接渲染 HTML 字符串通常需要使用
dangerouslySetInnerHTML
,但这可能带来 XSS(跨站脚本攻击)风险。html-react-parser
提供了一种更安全的方式来解析和渲染 HTML。
-
-
支持自定义转换规则
-
你可以自定义如何转换特定的 HTML 标签或属性,例如将
<a>
标签替换成 React 组件。
-
基本用法示例:
import parser from 'html-react-parser';const htmlString = '<div>Hello <strong>World</strong></div>';function MyComponent() {return <div>{parser(htmlString)}</div>;
}
渲染结果会显示:
Hello World("World" 是加粗的)
替代 dangerouslySetInnerHTML
的对比:
// 使用 dangerouslySetInnerHTML(不安全)
<div dangerouslySetInnerHTML={{ __html: htmlString }} />// 使用 html-react-parser(更安全、可控)
<div>{parser(htmlString)}</div>
其他功能:
-
可以替换特定标签为 React 组件:
parser('<img src="image.jpg">', {replace: (domNode) => {if (domNode.name === 'img') {return <MyImage src={domNode.attribs.src} />;}} });
-
过滤或修改属性,防止 XSS。
注意事项:
-
如果 HTML 来自用户输入,仍需确保内容经过消毒(sanitize),比如配合
DOMPurify
使用。 -
某些复杂的 HTML 结构(如 SVG 或表格嵌套)可能需要额外处理。
import DOMPurify from 'dompurify';
的作用是导入 DOMPurify 库,它是一个专门用于 对 HTML 内容进行消毒(Sanitize) 的 JavaScript 工具,主要用来防止 XSS(跨站脚本攻击) 等安全风险。
DOMPurify 的核心作用
当你的应用需要渲染 用户提交的 HTML(比如富文本编辑器、评论系统、动态消息等),直接使用 innerHTML
或 dangerouslySetInnerHTML
可能会导致恶意代码执行,例如:
<!-- 恶意用户提交的 HTML -->
<div>你好!<script>alert('XSS攻击!');</script>
</div>
如果直接渲染这段代码,<script>
标签会被执行,可能导致 数据窃取、用户劫持等安全问题。
DOMPurify 的作用就是过滤掉这些危险内容,只保留安全的 HTML 标签和属性。
import DOMPurify from 'dompurify';const dirtyHtml = `<div><p>这是一段<b>安全的</b>文本</p><script>alert('XSS!');</script><img src="x" onerror="alert('恶意代码')"></div>
`;// 使用 DOMPurify 清理 HTML
const cleanHtml = DOMPurify.sanitize(dirtyHtml);console.log(cleanHtml);
// 输出:<div><p>这是一段<b>安全的</b>文本</p><img src="x"></div>
关键变化:
-
<script>
被完全移除。 -
onerror
等危险属性被删除,只保留src
。 -
安全的 HTML(如
<p>
,<b>
)被保留。
常见使用场景
(1)配合 html-react-parser
安全渲染 HTML
import DOMPurify from 'dompurify';
import parser from 'html-react-parser';const userInput = '<div onclick="alert(1)">点击我</div>';const safeHtml = DOMPurify.sanitize(userInput);
const reactElements = parser(safeHtml);return <div>{reactElements}</div>;
// 渲染结果:<div>点击我</div>(onclick 被移除,不会触发弹窗)
(2)在 React 中替代 dangerouslySetInnerHTML
// ❌ 不安全的方式
<div dangerouslySetInnerHTML={{ __html: userInput }} />// ✅ 安全的方式
<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />
(3)Node.js 后端清洗 HTML
const createDOMPurify = require('dompurify');
const { JSDOM } = require('jsdom');const window = new JSDOM('').window;
const DOMPurify = createDOMPurify(window);const clean = DOMPurify.sanitize(dirtyHtml);
DOMPurify 的过滤规则
DOMPurify 默认允许 常见的安全 HTML 标签(如 <p>
, <a>
, <img>
),但会移除:
-
<script>
,<iframe>
,<embed>
等可执行代码 -
onclick
,onerror
,href="javascript:..."
等危险属性 -
style
属性中的危险 CSS(如expression()
)
自定义允许的标签/属性
const cleanHtml = DOMPurify.sanitize(dirtyHtml, {ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a'], // 只允许这些标签ALLOWED_ATTR: ['href', 'title'], // 只允许这些属性
});
与其他安全库的对比
工具 | 用途 | 特点 |
---|---|---|
DOMPurify | HTML 消毒(Sanitize) | 轻量级,专注于 XSS 防护 |
xss (npm 包) | HTML 消毒 | 中文社区常用,类似 DOMPurify |
validator.js | 通用输入验证 | 不专门处理 HTML |
html-react-parser | HTML → React 转换 | 需配合 DOMPurify 使用 |
四、总结
-
DOMPurify 用于清理 HTML,防止 XSS 攻击。
-
在渲染用户输入的 HTML 前,务必使用它进行过滤。
-
可配合
html-react-parser
或dangerouslySetInnerHTML
安全渲染动态内容。