ThinkPHP的{$name}语法默认不自动转义HTML,是框架设计而非漏洞;应使用{:$data.content}跳过转义或htmlspecialchars_decode解码,富文本须用HtmlPurifier白名单过滤。

模板变量输出不自动转义的默认行为
ThinkPHP 的 {$name} 语法默认不做 HTML 转义,这不是 bug,是框架明确的设计选择:把上下文安全责任交还给开发者。所以你看到 <p>Hello</p> 被原样渲染成文本,不是因为“被转义了”,而是因为你没告诉模板引擎“这段内容要当 HTML 解析”。
关闭转义的两种可靠写法
必须用冒号前缀或显式解码,不能依赖配置项“关掉”整个转义逻辑:
-
{:$data.content}—— 最直接,跳过所有默认过滤,原始 HTML 直出 -
{:htmlspecialchars_decode($data.content)}—— 仅当内容已被错误地 double-encoded(比如存库时多套了一层htmlspecialchars())才需要 - 别碰
template.default_filter配置去“全局关闭”,它会破坏 JSON 字段、URL 参数等非 HTML 上下文的输出
为什么 htmlspecialchars() 不该在入库前调用
这是开发中最常踩的坑:把用户提交的富文本先 htmlspecialchars() 再存进数据库,结果页面上永远显示 <p></p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill9263" title="Html2md"><img
src="https://img.php.cn/upload/skill/000/000/081/179249945220127.jpg" alt="Html2md" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill9263" title="Html2md" class="overflowclass">Html2md</a>
<p class="overflowclass">使用 Readability + Turndown 将 HTML 页面转换为干净的、Agent 友好的 Markdown。去除导航栏、广告、页脚、Cookie 横幅、社交按钮等干扰元素。支持 URL...</p>
</div>
<a rel="nofollow" href="/xiazai/skill9263" title="Html2md" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>。
- HTML 标签应以原始形态入库(字段类型设为
TEXT或MEDIUMTEXT) - 只在输出到 HTML 上下文时做一次转义或白名单过滤(富文本用
HtmlPurifier) - 用
Db::execute()拼 SQL 或create()前手动过滤,都会导致数据失真
富文本字段不能用 htmlspecialchars() 替代过滤
想靠 htmlspecialchars() 防 XSS?它会把合法的 <p><strong>Hi</strong></p> 变成纯文本,彻底破坏格式。
- 必须引入
HtmlPurifier,配白名单:$config->set('HTML.Allowed', 'p,strong,ul,ol,li,a[href|title],img[src|alt]') - 禁用正则删
<script></script>——绕过方式太多,<scr></scr>
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










