React应用中在textarea内展示自定义标签并规避XSS漏洞的方法
React中安全实现带标签的可输入区域方案
原生<textarea>只能展示纯文本,没法渲染带样式的标签,要实现你要的效果,得换个思路,同时严格防范XSS风险,具体方案如下:
核心思路:用contenteditable容器模拟输入框,搭配输入净化
放弃原生textarea,使用contenteditable="true"的div/section模拟输入区域,同时对用户输入的内容做严格过滤,只允许安全的标签结构。
1. 依赖XSS净化库
用DOMPurify来处理用户输入,它会自动过滤掉危险的HTML标签和属性,只保留你允许的内容。先安装依赖:
npm install dompurify
2. 实现自定义标签输入组件
下面是一个简化的React组件示例,实现标签添加、删除,同时保证输入安全:
import React, { useState, useRef } from 'react'; import DOMPurify from 'dompurify'; const TagInput = () => { const [content, setContent] = useState(''); const inputRef = useRef(null); // 处理输入内容变化,净化后更新 const handleInput = () => { if (!inputRef.current) return; // 净化内容,只允许span标签和特定类名、属性 const cleanContent = DOMPurify.sanitize(inputRef.current.innerHTML, { ADD_TAGS: ['span'], ADD_ATTR: ['class', 'data-tag'], ALLOWED_ATTR: ['class', 'data-tag'], FORBID_TAGS: ['script', 'iframe', 'a'], // 禁止危险标签 }); setContent(cleanContent); }; // 添加标签:用户输入逗号或回车时触发 const handleKeyDown = (e) => { if (e.key === ',' || e.key === 'Enter') { e.preventDefault(); const selection = window.getSelection(); if (!selection.rangeCount) return; const range = selection.getRangeAt(0); const tagText = range.startContainer.textContent.trim(); if (!tagText) return; // 创建标签元素 const tagElement = document.createElement('span'); tagElement.className = 'tag'; tagElement.dataset.tag = tagText; tagElement.innerHTML = `${tagText} <button onclick="this.parentElement.remove()">×</button>`; // 替换选中的文本为标签 range.deleteContents(); range.insertNode(tagElement); // 在标签后插入空白文本节点,保证继续输入 range.insertNode(document.createTextNode(' ')); range.setStartAfter(tagElement.nextSibling); range.setEndAfter(tagElement.nextSibling); selection.removeAllRanges(); selection.addRange(range); // 手动触发输入处理 handleInput(); } }; return ( <div ref={inputRef} contentEditable onInput={handleInput} onKeyDown={handleKeyDown} dangerouslySetInnerHTML={{ __html: content }} style={{ border: '1px solid #ccc', padding: '8px', minHeight: '100px', borderRadius: '4px', }} /> ); }; export default TagInput;
3. 关键安全点
- 严格过滤内容:通过DOMPurify的配置,只允许必要的标签(比如示例中的span)和属性,禁止所有可能触发XSS的标签(如script、iframe)。
- 避免直接渲染用户输入:所有插入到页面的内容都必须经过DOMPurify净化,再通过
dangerouslySetInnerHTML渲染。 - 标签交互安全:删除按钮的事件直接绑定在元素上,避免使用eval或危险的事件绑定方式。
4. 替代方案:使用成熟的富文本编辑器
如果不想自己造轮子,可以选择自带XSS防护的富文本编辑器,比如:
react-quill:支持自定义格式,可配置允许的内容类型slate.js:基于React的可定制富文本框架,能精确控制内容结构和安全规则
这些编辑器通常内置了输入净化机制,只需配置允许的标签格式即可。
内容的提问来源于stack exchange,提问作者Jeroen Beljaars
相关产品推荐
相关产品推荐

