不能依赖param()处理敏感字段,因其合并路由/get/post参数且绕过全局过滤链,不受default_filter影响,也不支持字段级过滤;关键字段须用input()或验证器。

ThinkPHP5 默认不自动过滤或验证用户输入,必须显式配置或调用才生效。直接用 input() 不加参数、或误用 param(),等于裸奔。
为什么不能依赖 param() 处理敏感字段
ThinkPHP5 的 param() 会合并路由变量、GET、POST,且绕过全局过滤链;一旦路由中混入用户可控参数(如 /user/:id),param('id') 可能返回未过滤的原始值。
-
param()不受default_filter配置影响,也不支持字段级过滤链 - 比如
param('content')和input('content')行为完全不同:前者可能含未转义 HTML,后者可配htmlspecialchars|trim - 登录、注册、评论等场景,必须用
input()或显式验证器,禁用param()取关键字段
input() 的三种过滤写法及坑点
input() 是 ThinkPHP5 安全取值的主入口,但写法决定是否真安全:
- 全局默认过滤只对
input()有效,需在config/app.php中配置:'default_filter' => 'htmlspecialchars,trim' - 单字段覆盖过滤链:
input('email', '', 'htmlspecialchars|strip_tags|strtolower')—— 注意顺序:先strip_tags再htmlspecialchars才防 XSS,反了会失效 - 验证型过滤慎用:
input('age', 0, 'intval')看似安全,但intval('12abc')返回12,不是严格验证;应改用filter_var(input('age'), FILTER_VALIDATE_INT)+ 范围检查
验证器类比 input() 过滤更可靠
复杂业务(如密码强度、唯一性、关联字段校验)必须用验证器类,input() 的字符串过滤链无法处理逻辑判断:
- 定义验证规则时,
require|email|unique:user,email中的unique会查库,而input()做不到 - 验证器自动调用
filter_var()底层,例如email规则实际执行filter_var($value, FILTER_VALIDATE_EMAIL) - 错误信息统一收集,避免
if (!filter_var(...)) die()这种硬中断写法 - 示例调用:
$validate = validate('User'); if (!$validate->check($data)) { $this->error($validate->getError()); }
别漏掉输出环节的 htmlspecialchars()
即使输入层用了 input() + 验证器,模板里直接 {$user.content} 仍可能触发 XSS —— ThinkPHP5 的模板引擎默认不自动转义。
- 模板中必须手动转义:
{:htmlspecialchars($user.content, ENT_QUOTES, 'UTF-8')}或启用模板自动转义(配置'default_filter' => 'htmlspecialchars'在模板配置中) - 数据库读出的数据属于「不可信输出」,和用户输入同等级对待,不能因为「已入库」就跳过转义
- JSON 接口也要注意:
json_encode()不自动转义 HTML 实体,需在数据进json_encode()前做htmlspecialchars()
最易被忽略的是:验证器和 input() 过滤只管「进」,不管「出」;而 XSS 攻击常发生在输出渲染阶段。一个字段从表单提交 → 验证器校验 → 数据库存储 → 模板输出,四个环节里只要漏掉任意一环的过滤或转义,防线就破了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











