Next.js中如何安全格式化Props传递的文本(添加span/strong等)
如何通过Props实现可复用的文本格式化组件并避免XSS注入
问题场景
你需要开发一个可复用的React组件,支持通过props传入带自定义标记的文本(比如$*...*$、$**...**$),自动将这些标记转换为对应的HTML标签(strong、span)及样式,同时要防范XSS注入风险。组件使用示例如下:
<HeroCourse title="La $*grammaire*$ de l’espagnol" description="Toutes les $**règles**$ de grammaire pour apprendre à lire, écrire et parler espagnol" />
现有代码的问题
你当前的实现存在几个明显缺陷:
- 正则匹配顺序错误:先处理普通
*...*标记,再处理$*...*$,会导致$*grammaire*$中的*被提前替换,破坏完整的自定义标记,最终无法正确解析特殊格式。 - 样式硬编码:直接在替换的HTML中写内联样式
style="color: red;",不利于样式维护和组件复用,不符合React的样式管理规范。 - XSS处理时机可优化:虽然使用了DOMPurify,但先解析语法再净化的流程,不如先净化原始输入再解析更稳妥。
优化后的实现方案
1. 调整正则匹配顺序
优先处理带$的特殊标记,再处理普通*和**标记,避免特殊标记被提前拆分。
2. 用CSS Modules管理样式
将样式写入模块文件,替代内联样式,提升可维护性和复用性。
3. 先净化再解析
先对用户输入的原始文本进行XSS净化,再处理自定义语法,彻底阻断恶意代码注入路径。
完整代码
import Input from './../UI/buttons/Input'; import DOMPurify from 'dompurify'; import styles from "./HeroCourse.module.css"; function parseCustomSyntax(text) { // 先处理带$的自定义标记,避免被普通*规则破坏 text = text.replace(/\$\*([^$]*)\*\$/g, `<strong class="${styles.highlight}">$1</strong>`); text = text.replace(/\$\*\*([^$]*)\*\*\$/g, `<span class="${styles.emphasis}">$1</span>`); // 再处理普通的*和**标记 text = text.replace(/\*([^*]*)\*/g, `<span class="${styles.highlight}">$1</span>`); text = text.replace(/\*\*([^*]*)\*\*/g, `<strong>$1</strong>`); return text; } function HeroCourse({ title, description, inputProps }) { // 先净化原始输入,再解析语法,双重防护XSS const cleanTitle = DOMPurify.sanitize(title); const cleanDescription = DOMPurify.sanitize(description); const formattedTitle = parseCustomSyntax(cleanTitle); const formattedDescription = parseCustomSyntax(cleanDescription); return ( <div className={styles["hero-course-container"]}> <div className={styles["hero-course"]}> <h2 dangerouslySetInnerHTML={{ __html: formattedTitle }} /> <p dangerouslySetInnerHTML={{ __html: formattedDescription }} /> <Input {...inputProps} /> </div> </div> ); } export default HeroCourse;
配套的CSS Modules(HeroCourse.module.css)
.highlight { color: red; } .emphasis { font-style: italic; /* 可根据需求自定义span样式 */ }
重点说明
- 正则顺序是关键:必须先处理带
$的特殊标记,否则普通*会拆分特殊标记,导致解析失败。 - CSS Modules优势:避免样式污染,后续修改样式只需调整CSS文件,无需改动JS代码,提升组件复用性。
- XSS防护逻辑:先净化原始输入再解析语法,确保用户输入中的恶意代码在解析前就被清理,结合
dangerouslySetInnerHTML前的净化,实现双重安全保障。 - 扩展性强:后续新增自定义标记(如
$#...#$),只需在parseCustomSyntax中添加对应正则替换规则即可,无需修改组件核心结构。
内容的提问来源于stack exchange,提问作者el ton
相关产品推荐
相关产品推荐

