ThinkPHP路由参数:id必须用pattern()显式正则约束,否则任意字符串都合法;它不校验注入元字符,需预检用户正则安全性;验证器不自动处理路由变量,须手动提取并校验。
ThinkPHP 的
这类
路由
参数默认不校验格式,
会直接把
传进控制器——这不是“灵活性”,是注入入口。
路由参数必须用
显式约束
是唯一能对
形式路径变量做正则校验的机制,不加它,任何字符串都算合法。
只对
生效,
或
不走这条路,得另配验证器
必须写在路由定义链上,比如
多个参数一起约束:
别写
就完事——要防回溯爆炸,优先用原子组或限制长度,例如
(1~8位正整数)
不校验注入元字符,得自己拦
类 PCRE 指令
TP 的
只管你传的值是否匹配正则,不管这个正则本身安不安全。攻击者若提交
这种恶意模式(虽罕见但可能),框架不会报错。
真正危险的是:你把用户输入当正则去
—— 这属于运行时编译,TP 不介入
必须在调用
前预检:
、过滤控制字符、再用
+
别试图用正则去“清洗”正则——
极易漏判,白名单预检更可靠
路由参数不进
,验证器不会自动校验它
很多人以为写了
就万事大吉,但验证器默认只处理
(即 GET/POST/PUT 数据),
是从 URL 路径解析出来的,根本不在里面。
立即学习
“
PHP免费学习笔记(深入)
”;
手动提取:
或
(注意后者默认不读路由变量,得加
修饰符:
)
构造数组显式校验:
,不能依赖自动绑定
如果用
规则,确保数据库查询走参数绑定,不是字符串拼接:
,不是
最常被跳过的点:路由参数校验是两层动作——
拦住非法格式,验证器补足业务逻辑(如存在性、权限)。少一层,就等于把门虚掩着让攻击者推。
:iduser/abc$id = 'abc'pattern()pattern():xxx:xxx/:xxx??id=123Route::get('user/:id', 'User/read')->pattern(['id' => '\d+'])->pattern(['id' => '\d+', 'token' => '[a-zA-Z0-9_]{16,32}'])\d+[1-9]\d{0,7}pattern()(*COMMIT)pattern()/(?{system("id")})/preg_match()preg_match($userPattern, $data)strpos($userPattern, "\x00") !== false@preg_match($userPattern, '')preg_last_error() === PREG_NO_ERRORpreg_replace('/\(\*\w+/i', '', $input)$request->param()['id' => 'require|number']$request->param():id$id = $this->request->route('id')input('id')/sinput('id/s')$validate->check(['id' => $id])exists:user,idwhere(['id' => $id])"id = $id"pattern()