动态路由参数必须经过格式校验,禁用(:any)改用带约束正则,控制器中二次校验,强制类型转换+白名单验证,多段参数需分层过滤并逐段校验。

动态路由参数必须经过格式校验
CodeIgniter 4 中通过 (:any) 或正则捕获的路由参数默认不校验内容,直接拼入 SQL 查询或渲染模板极易引发注入、路径遍历或 XSS 风险。
第一步:在路由定义中禁用宽泛匹配,改用带约束的正则表达式。例如匹配博客 slug,只允许小写字母、数字和短横线:
$routes->get('post/([a-z0-9\-]+)', 'BlogController::show/$1');
第二步:在控制器方法中再次校验参数,不能依赖路由层的正则作为唯一防线。因为中间件或手动调用可能绕过路由匹配:
if (! preg_match('/^[a-z0-9\-]+$/i', $slug)) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); }
【参数未二次校验会导致数据库查询被注入绕过】
传参时避免直接暴露原始值
不要把用户提交的原始 slug 直接传给模型的 where() 方法,尤其当字段类型为整型却用字符串接收时。
方法一:强制类型转换 + 白名单验证
若 slug 实际对应的是整型 ID(如 /article/123),应先转为 int 再查:
$id = (int) $slug; if ($id
方法二:使用模型的严格查询接口
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
PostModel 中定义专用查找方法,内部封装校验逻辑:
public function findBySlug(string $slug): ?array { if (empty($slug) || ! preg_match('/^[a-z0-9\-]{3,64}$/', $slug)) { return null; } return $this->where('slug', $slug)->first(); }
URL 中含多段参数时需分层过滤
当路由形如 /category/{cat}/{subcat}/{post},不能只校验最后一段。
① 在路由配置中拆解各段并分别约束:
$routes->get('category/([a-z0-9\-]+)/([a-z0-9\-]+)/([a-z0-9\-]+)', 'CategoryController::view/$1/$2/$3');
② 控制器中逐段解包并校验:
[$cat, $subcat, $post] = [$segments[0], $segments[1], $segments[2]];
③ 对 category 段做白名单比对(防止伪造 admin、system 等敏感路径):
if (! in_array($cat, ['news', 'blog', 'docs'], true)) { throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(); }
④ subcat 和 post 段仍需执行长度与字符集限制,避免超长 URL 触发缓存溢出或日志截断。










