ThinkPHP 8.0 不再提供 default_filter 配置项,模板变量 {$var} 默认不转义,必须手动按上下文显式处理:HTML 用 htmlspecialchars($var, ENT_QUOTES | ENT_HTML5, 'UTF-8'),JS 用 json_encode() 带完整标志,富文本必须用 HTMLPurifier 白名单净化。

ThinkPHP 8.0 不再提供 default_filter 配置项,也不对模板变量默认转义——XSS 防御必须手动、按上下文显式处理,依赖框架“自动兜底”会直接导致反射型或存储型 XSS。
模板里 {$var} 直接输出就是 XSS 入口
TP8 模板引擎完全取消了默认 HTML 转义,{$name} 等价于 <?php echo $name; ?>。用户提交 <script>alert(1)</script>,页面就会执行。
- 补救写法:用
{:htmlspecialchars($name, ENT_QUOTES | ENT_HTML5, 'UTF-8')}替代{$name} - 简写语法
{$name|html}可用,但仅限 TP8.0.1+ 版本,且它内部调用的是htmlspecialchars($name, ENT_COMPAT)—— 单引号不转义,onerror="alert(1)"仍可绕过 - 属性值场景(如
title="{$title}")必须确保引号包裹,否则即使内容已转义,空格也会截断属性并注入事件
JSON 接口返回用户数据时 htmlspecialchars() 是错的
常见错误:<script>var data = { "content": "<?php echo htmlspecialchars($content); ?>" };</script> —— 这根本防不住 XSS,因为 htmlspecialchars() 不处理 JS 字符串边界、Unicode 行分隔符(\u2028)、反斜杠逃逸等。
- 正确做法:统一用
json_encode(),且必须带标志:echo json_encode(['content' => $content], JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_QUOT); - 若数据要塞进内联
<script>,JSON_HEX_QUOT必须开启,防止双引号闭合 - 绝对不要拼接 JSON 字符串,哪怕加了
htmlspecialchars()
富文本内容不能用 htmlspecialchars(),必须走 HTMLPurifier 白名单
htmlspecialchars() 对 <img src="x" onerror="alert(1)"> 完全无效,只会把它变成可见文本,破坏排版;而 strip_tags() 或正则过滤极易被绕过。
立即学习“PHP免费学习笔记(深入)”;
- 安装:
composer require ezyang/htmlpurifier - 配置必须显式声明白名单:
$config->set('HTML.Allowed', 'p,b,i,u,a[href|title],img[src|alt|width|height]'); - 关键安全项必须设:
$config->set('Core.RemoveScriptContents', true);、$config->set('URI.AllowedSchemes', ['http', 'https', 'mailto']); - 禁止在控制器里每次 new HTMLPurifier(),应注册为容器单例,避免重复加载 DTD 和编译规则
控制器里 assign() 前转义是自毁行为
有人习惯在 Controller 中写 $data['title'] = htmlspecialchars($input); $this->assign($data);,这会让同一变量无法复用于 JS 变量、URL 参数、meta content 等不同上下文。
- 变量应保持原始状态入库、传参、assign,只在最终输出点按需编码
- 比如
$title既要进<h1>{$title}</h1>,又要进<meta name="description" content="{$title}">,还要进<script>var t = <?php echo json_encode($title); ?></script>—— 提前转义就全乱了 - 真正容易被忽略的是非典型输出点:CSS 的
content属性、data-属性、SVG 的xlink:href,这些地方连htmlspecialchars()都不适用,得靠上下文专用编码



















