You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 16:23:19