PHP分页怎么用API分页令牌_PHP分页令牌安全机制【方法】

5次阅读

php api分页首选游标(cursor)而非page/limit,因其基于唯一有序字段避免漏数跳页;安全cursor需签名+载荷+过期时间组合,防篡改重放;且仅短期有效,须明确告知前端并妥善处理NULL、解码失败、软删除等边界情况。

PHP分页怎么用API分页令牌_PHP分页令牌安全机制【方法】

PHP API分页用什么令牌?cursor 是首选,不是 pagelimit

传统 page=3&limit=20 在高并发或数据动态增删时容易漏数、重复或跳页,API 分页应优先用游标(cursor)——它基于上一页最后一条记录的唯一、有序字段(如 idcreated_at),服务端只返回下一页的起始标记。

实操建议:

立即学习PHP免费学习笔记(深入)”;

  • cursor 值必须是 URL 安全编码的(如 base64_encode("12345")),不能直接暴露原始主键或时间戳
  • 首次请求不带 cursor,服务端默认从第一条开始;后续请求必须携带上一页响应中的 next_cursor
  • 不要用 offset 做游标,它随删除/插入漂移,cursor 必须绑定不可变排序字段值
  • 前端需忽略 cursor 内容,只透传;后端解码后严格校验格式和长度(防注入或越界)

怎么生成安全的 cursor 字符串

安全的 cursor 不是简单 base64 编码 ID,而是「签名 + 有效载荷 + 过期时间」组合,防止篡改和重放。

实操建议:

立即学习PHP免费学习笔记(深入)”;

  • 构造载荷数组:['id' => 12345, 'ts' => time(), 'exp' => time() + 300](5 分钟过期)
  • hash_hmac('sha256', json_encode($payload), $secret_key) 签名,拼接成 $payload_b64 . '.' . $signature_b64
  • 解码时先分割,验证签名,再检查 exp 是否过期、id 是否为正整数、是否在合理范围(如不超过最大 ID 的 2 倍)
  • 避免把数据库密码、密钥硬编码进逻辑;用 $_ENV['CURSOR_SECRET'] 或配置中心加载

为什么不能把 cursor 当作永久分页句柄?

cursor 本质是临时快照锚点,不是数据库游标。底层数据变更、索引重建、归档策略都可能让旧 cursor 失效。

常见错误现象:

  • 用户下拉到底后停留 10 分钟再点“加载更多”,返回 400 Bad Request 或空结果
  • 后台执行了大批量 delete,导致某段 cursor 对应的记录已不存在,查询无匹配行
  • 同一 cursor 多次请求返回不同结果(因新插入记录挤入排序位置)

所以必须明确告知前端:游标仅短期有效;服务端要返回 next_cursornull(表示末页),而不是尝试“恢复”失效游标。

PHP 实现里最容易被忽略的三个细节

真正上线后出问题的,往往不是逻辑主干,而是这几个边界点:

  • mysql 排序字段含 NULL:用 ORDER BY created_at DESC NULLS LASTpostgresql 支持),但 MySQL 不支持 NULLS LAST,得改写为 ORDER BY ISNULL(created_at), created_at DESC
  • 游标解码失败时,别直接 throw new Exception(),应统一返回 400 + {"Error": "invalid_cursor"},避免泄露内部错误
  • 当用户传入的 cursor 指向的记录已被软删除(is_deleted = 1),查询要跳过它并找下一个有效记录,否则会卡死在“不可见”的断点上

游标分页的安全性和稳定性,不在加密多强,而在对数据一致性、时效性、异常路径的诚实处理。越想“无缝续传”,越要接受“断点可丢”。

text=ZqhQzanResources