CodeIgniter中接收数字参数需三层防护:Controller用filter_var校验并转换整型,路由用:num或正则约束,Model层须再次断言is_int;因框架不自动类型转换,字符串混入易致SQL异常或安全风险。

Controller 中接收数字参数时怎么防字符串混入
CodeIgniter 不会自动把 $_POST 或 URL 参数转成整型,哪怕你传的是 pid=123,$this->input->post('pid') 返回的仍是字符串。直接拿它拼 SQL 或做比较(比如 id > $pid)会导致隐式类型转换、查询失效甚至注入风险。
- 显式用
(int)或filter_var($val, FILTER_VALIDATE_INT)转换,别依赖框架“猜”类型 - 用
$this->input->post('pid', true)启用 XSS 过滤——但注意:这不改变类型,只过滤 HTML 实体 - 空字符串、
"0"、"123abc"经(int)会变成0、0、123,所以必须先校验是否合法数字再转 - 推荐组合:
$pid = filter_var($this->input->post('pid'), FILTER_VALIDATE_INT); if ($pid === false) { /* 拒绝非法输入 */ }
Model 查询中怎么安全使用数字参数
即使 Controller 已转整型,Model 层仍要防御性检查——尤其当方法可能被其他地方调用时。直接把未验证变量塞进 where() 或 limit() 是高危操作。
-
where('id >', $pid)如果$pid是null或空数组,CI4 会生成id >这种语法错误 SQL -
limit()接收非正整数(如-5、0)可能跳过数据或报错,取决于数据库驱动 - 在 Model 方法开头加判断:
if (!is_int($pid) || $pid - 对分页类参数(如
offset、limit)额外限制上限,避免恶意请求拖垮数据库
URL 路由参数里的数字怎么强制校验
CI4 路由支持正则约束,比在 Controller 里手动 filter_var 更早拦截非法值——请求根本不会进 Controller。
- 在
app/Config/Routes.php中写:$routes->get('news/(:num)', 'News::view/$1')->constraints(['id' => '\d+']); -
:num是 CI4 内置简写,等价于\d+;但注意它不阻止前导零(如/news/007),若需严格正整数,用完整正则[\d]{1,10} - 约束失败时返回 404,不执行控制器——这是性能和安全双重收益
- 不要依赖
:segment接数字,它啥都接,等于没限
表单提交的 number 输入框为什么拦不住非法值
<input type="number" min="1" max="999"> 的 min/max 只控制浏览器增减按钮和部分键盘行为,用户仍可粘贴或手动输入 "abc"、"-1000"、"1.5",后端必须重验。
- 前端 JS 补一层
oninput="value = value.replace(/[^0-9]/g, '')"只是体验优化,不能替代后端校验 - CI4 的表单验证规则
integer和greater_than[0]可用,但仅对$this->validate()生效,不覆盖$this->input->post()原始值 - 真正可靠的做法:路由约束 + Controller 类型转换 + Model 输入断言,三层漏斗式过滤
实际最易忽略的是路由约束与 Model 层的配合——很多人只在 Controller 转一次类型,却让 Model 方法裸奔接收,一旦该方法被 CLI 命令或 API 其他入口调用,防线就塌了。


















