thinkphp分页需手动校验page和size参数,因paginate()默认不防注入;必须用filter_input()做类型+范围双校验,并显式传入数组配置,否则易引发sql注入、整数溢出或服务拒绝。

ThinkPHP分页本身不自动防注入,page、limit、size 这类参数若未经校验,直接参与 SQL 构造或 OFFSET 计算,就会引发 SQL 注入、整数溢出、数据库拖库或服务拒绝(如 limit=9999999)等真实风险。
为什么 paginate() 不能代替参数过滤
ThinkPHP 的 paginate() 方法只负责查询构造和分页渲染,它默认信任传入的页码值——比如你写 User::paginate(15),框架会从 $_GET['page'] 自动读取并用于计算 OFFSET,但不会验证这个值是不是正整数、有没有超限、是否含非法字符。
- 攻击者发请求:
?page=1%20OR%201=1→ 若你用input('page')且没过滤,可能被转成字符串后拼进 SQL(尤其在自定义查询中) -
?page=-1或?page=abc可能导致OFFSET计算为负数或 0,绕过业务逻辑限制 -
?size=0或?size=1000000若未设上限,LIMIT会直接压垮 MySQL 连接池
必须对 page 和 size 做显式整型校验
别依赖 input('page/d', 1) 中的 /d 后缀——它本质是 (int) 强转,对 page=1abc 仍返回 1,掩盖了非法输入。真正安全的做法是用 filter_input() 配合 FILTER_VALIDATE_INT 做类型+范围双校验。
- 校验
page:必须是 ≥1 的整数,上限建议设为 10000(避免翻到极深页) - 校验
size(或list_rows):必须是 1–100 区间内的整数,禁用 0 或超大值 - 示例代码:
$page = filter_input(INPUT_GET, 'page', FILTER_VALIDATE_INT, [ 'options' => ['default' => 1, 'min_range' => 1, 'max_range' => 10000] ]); $size = filter_input(INPUT_GET, 'size', FILTER_VALIDATE_INT, [ 'options' => ['default' => 15, 'min_range' => 1, 'max_range' => 100] ]); if ($page === false || $size === false) { http_response_code(400); die('Invalid pagination parameters'); }
在 paginate() 中正确透传已校验参数
ThinkPHP 的 paginate() 支持数组参数,这是控制页码和条数的唯一可控方式。若你跳过这步,直接用数字参数(如 ->paginate(15)),框架会再次从 $_GET 读取 page,等于绕过了你刚做的校验。
- 错误写法:
User::paginate(15)→ 框架自动解析$_GET['page'],未经过滤 - 正确写法:
User::paginate(['list_rows' => $size, 'page' => $page])→ 显式传入已校验变量 - 若需保留搜索参数(如
keyword),加到query键里:['list_rows' => $size, 'page' => $page, 'query' => input('only', ['keyword'])]
复杂查询下 total() 不准时,更要手动校验 offset 范围
当分页涉及 LEFT JOIN、子查询或 UNION 时,ThinkPHP 自动生成的 COUNT(*) 可能漏统计或报错,导致 $users->total() 返回 0 或远小于实际值。此时若用户强行访问 ?page=999999,OFFSET 计算结果可能远超表实际行数,MySQL 虽不报错,但返回空数据,同时浪费一次 COUNT 查询。
- 解决方案:用校验后的
$page和$size手动算$offset = ($page - 1) * $size,再查一次表总行数(缓存或覆盖索引优化),若$offset >= $total,直接返回空或跳转首页 - 更轻量做法:启用 simple 分页模式(
'simple' => true),它不查总数,只取$size + 1条判断“是否有下一页”,天然规避超页问题
最易被忽略的一点:校验必须在 paginate() 调用前完成,且传参必须用数组形式;任何把 input() 结果直接塞进数字参数调用的行为,都等于把校验逻辑形同虚设。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











