富文本数据在数据库总的存储问题

所属分类:php | 浏览:8 | 发布于 2026-04-08

标题起的高大上,实际上就是富文本在保存到数据库时,是存储原始标签数据,还是转义后数据的问题。

1、先看实际案例

下图右边是本博客在数据库中默认存储的内容,左边是使用thinkcmf开发是默认存储的内容。

很显然,本博客mysql中存储的是未转义的数据,thinkcmf的mysql中存储的是转义后的数据。

2、两个概念

2.1、html标签

html标签是构成html文档的基本单位,是用尖括号<>包裹的关键词,用于高速浏览器如何解析、渲染页面内容(比如定义标题、段落、图片、链接等),模式HTML的核心语法。

核心特点

  1. 双标签(有开始和结束,如 <p></p>)和单标签(自闭合,如 <img/> <br/>);
  2. 浏览器会识别并执行标签的功能,不会直接显示标签本身;
  3. 部分标签带属性,补充功能(如 <img src="图片地址" alt="描述"/>)。

2.2、html实体

html实体是用特定编码表示html特殊字符的方式,这些表示以&开头,以;结尾,用于在页面中显示哪些浏览器会被解析为语法的特殊字符(),或显示一些无法直接输入的特殊字符(例如空格、版权符©)。

核心特点

  1. 浏览器会将实体编码还原为对应的原始字符并显示,不会当作 HTML 语法解析;
  2. 解决「特殊字符被浏览器误解析」的问题(比如想显示<,直接写会被认作标签开头,必须用实体&lt;);
  3. 命名实体(如 &lt;)和数字实体(如 &#60;),效果一致,命名实体更易记。

2.3、测试代码

<!-- 情况1:直接写< >,浏览器认作HTML标签,解析功能 -->
<p>这是<h1>测试</h1>文本</p>
<!-- 页面效果:这是【大号加粗的测试】文本(<h1>被解析为标题标签) -->

<!-- 情况2:用HTML实体写&lt; &gt;,浏览器显示原始字符,不解析 -->
<p>这是&lt;h1&gt;测试&lt;/h1&gt;文本</p>
<!-- 页面效果:这是<h1>测试</h1>文本(直接显示尖括号和h1,无标题效果) -->

显示效果:

当使用html实体时,浏览器直接显示原始字符,不解析。

3、htmlspecialchars() 函数

htmlspecialchars($str) 的作用:把字符串中的 HTML 特殊字符()转换成对应的 HTML 实体;目的是:让浏览器只显示字符,不解析为HTML标签,这样既避免页面布局错乱,又防止XSS攻击(比如用户输入<script>,转成&lt;script&gt;后就不会被执行)。

例如:

<?php
$str = '<script>alert("XSS")</script>';
// 转义:把< > " & 转成实体
$escaped = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
echo $escaped;
// 输出的内容:&lt;script&gt;alert(&quot;XSS&quot;)&lt;/script&gt;
// 浏览器效果:直接显示<string>alert("XSS")</string>,不会执行弹窗
?>

4、htmlspecialchars_decode() 函数

htmlspecialchars_decode() 函数用于还原转义后的文本(比如后台编辑、数据还原)。和htmlspecialchars() 函数是互逆操作。

函数 核心作用 常用场景
htmlspecialchars 特殊字符→HTML 实体(编码) 纯文本输出到页面(防 XSS、防标签解析)
htmlspecialchars_decode HTML 实体→特殊字符(解码) 还原转义后的文本(如后台编辑、数据还原)

xss攻击实战:

<?php
// 用户恶意输入的评论
$userComment = '<script>alert("XSS攻击")</script>';

// 转义后输出(安全,浏览器仅显示文本,不执行脚本)
echo htmlspecialchars($userComment, ENT_QUOTES, 'UTF-8');
// 输出:&lt;script&gt;alert(&quot;XSS攻击&quot;)&lt;/script&gt;

// 若需要将转义后的评论还原为原始内容(比如后台编辑)
$editComment = htmlspecialchars_decode(htmlspecialchars($userComment));
echo $editComment; // 输出:<script>alert("XSS攻击")</script>
?>

5、htmlentities() 函数

htmlentities()会转义所有 HTML 实体(包括中文),实战中极少用,容易导致乱码;而htmlspecialchars() 只会处理<>&"' 这5个字符。

6、最终结论

这是豆包给的结论

  • 绝对不能用 htmlspecialchars() 转义富文本后存库
     
    富文本本身就是带<p>、<img>、<div>等 HTML 标签的内容,用这个函数会把标签转成&lt;p&gt;,取出来展示时就变成纯文本了,富文本直接失效。
     
  • 必须做【数据库转义】(防 SQL 注入)
     
    富文本里可能包含单引号'、双引号"、反斜杠\等字符,直接拼接 SQL 会导致注入漏洞,必须转义后再入库
     
  • 展示到页面时:不需要二次转义
     
    直接输出富文本即可(如果是用户提交的富文本,需要额外做 XSS 过滤,和数据库转义是两回事)。

很明显,thinkcmf的做法和豆包给的结论是完全相反的。

海涛贝塔(https://haitaobeta.com)属于海涛个人博客,欢迎浏览使用

联系方式:qq:52292959 邮箱:52292959@qq.com

备案号:粤ICP备18108585号 友情链接