thinkphp 6 的 input() 默认不过滤危险字符,仅去除首尾空白并做类型转换;/s 仅表示字符串强制转换,非安全过滤;sql 拼接须用参数绑定或整型转换,html 输出须手动 htmlspecialchars。

ThinkPHP 6 的 input() 默认是否过滤危险字符?
不过滤。ThinkPHP 6 的 input() 是纯数据读取函数,它只做类型转换和默认值填充,不会自动 strip_tags、不转义 SQL 特殊字符、也不拦截 <script></script> 或 javascript: 等组合。很多人误以为「框架自带防护」,结果在拼接 SQL、输出到模板、写入日志时直接中招。
- 默认行为是原样返回用户传入的字符串(仅去除首尾空白)
- 即使开启
app_debug = false,也不会额外过滤 -
input('name')和input('name/s')中的/s只表示「字符串类型强制转换」,不是「安全过滤」
哪些地方必须手动过滤?看使用场景
不是所有参数都要一刀切过滤,关键看后续怎么用:
-
拼 SQL 查询(尤其是
where数组或闭包里用字符串拼接):必须用Db::name()->where()的参数绑定,或至少用input('id/d')强制转整型,input('name/s')不防注入 -
输出到 HTML 页面(
echo $name或模板变量):必须用htmlspecialchars($name, ENT_QUOTES, 'UTF-8'),ThinkPHP 模板引擎的{$name}默认不转义,要写成{:htmlspecialchars($name)}或启用default过滤器(但别依赖全局 default,容易漏) -
写入文件路径、shell 命令、JSONP 回调名:必须白名单校验,比如用
in_array(input('callback'), ['cb1', 'cb2']),而不是试图“过滤掉点号和括号”
filter 参数和 validate 验证器真能防注入吗?
不能替代上下文感知的处理。它们只是前置校验,不是执行时的安全兜底:
-
input('email', '', 'htmlspecialchars')看似过滤了,但如果后续又做了urldecode()或二次拼接,就白费 -
validate规则如email|alphaNum对防止 XSS 无效,alphaNum拦不住onerror=alert(1) - 验证器的
regex如果写成^[\w-.@]+$,依然可能放过javascript:alert(1)—— 因为冒号和括号在 Unicode 中属于 \w 边界情况
更稳妥的做法是:
- 在控制器里按用途明确调用处理函数:
input('desc/s')+htmlspecialchars()用于输出,input('id/d')用于 ID 查询 - 不依赖验证器做「通用过滤」,验证器只管业务规则(长度、格式、存在性)
ThinkPHP 自带的 Request::filter() 为什么很少人用?
因为它是全局预处理,一旦开启,所有 input() 都会走一遍回调,但问题在于:
- 它无法区分「这个参数是要进 SQL 还是进 HTML」,只能统一处理,容易过度转义(比如把合法的 JSON 字符串里的双引号全干掉)
- 默认关闭,且文档没强调风险;开启后如果回调里用了
strip_tags(),会导致富文本编辑器提交的<p></p>直接变空 - 实际项目中,90% 的注入漏洞出在「开发者忘了处理」,而不是「框架没提供接口」—— 所以与其配全局 filter,不如在 IDE 里给
input()加个检查插件,或用 Psalm/PHPStan 标注参数用途
真正需要关注的是:每次拿到 input() 后,你接下来那一行代码打算怎么用它。那个「接下来」,才是防护的起点。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










