PHP 5 中生成随机数字的常见误区是混淆随机性与安全性,误用 rand()/mt_rand() 等非加密函数于验证码等安全场景,且存在前导零遗漏、uniqid()/md5(time()) 伪随机、输入校验不一致等问题。

PHP 5 生成随机数字的常见误区,核心在于混淆“随机性”和“安全性”,把适用于演示或游戏场景的函数,误用于需防批量攻击、撞库或重放的业务中(如验证码、密码重置码、会话令牌等)。
误用 rand() 或 mt_rand() 替代加密安全随机源
PHP 5 中 rand() 和 mt_rand() 均基于确定性算法(如梅森旋转),其输出可被预测:
- 只要知道种子(
mt_srand($seed))和已生成的部分序列,就能反推出后续所有值; - 即使未显式设种,PHP 启动时默认用时间戳+进程ID等弱熵播种,同一秒内多次调用极易产生高度相似甚至重复的序列;
- 攻击者可用工具如
php_mt_seed在数秒内爆破出种子,从而完全控制随机结果。
错误理解“范围”导致位数缺失(尤其验证码)
写成 mt_rand(100000, 999999) 生成“六位数”,看似合理,实则遗漏前导零:
- 该写法永远无法生成
001234、099999这类含前导零的字符串; - 而验证码展示和比对必须是严格 6 位字符串,不是数值比较;
- 正确路径应是先生成
0–999999的整数,再用sprintf('%06d', $n)格式化,而非依赖范围截断。
拿 uniqid() 或 md5(time()) 当随机数用
这些函数本质是唯一标识符生成器,不是随机数生成器:
立即学习“PHP免费学习笔记(深入)”;
-
uniqid()基于微秒时间戳,连续调用返回值高度有序,且无真正随机成分; -
substr(md5(time()), 0, 6)在同一秒内多次执行必然返回相同结果,极易被绕过; - 它们不可控、不可靠、不可重现(在安全意义上),更谈不上抗预测。
忽略输入清洗与比对逻辑不一致
后端生成的是干净的 6 位数字字符串,但用户输入常含空格、换行、全角字符甚至字母 O/l:
- 直接用
===比对原始输入,几乎必失败; - 未做
trim()、未用正则清除非数字(preg_replace('/[^0-9]/', '', $input))、未截取前 6 位并补零,就会让合法输入被拒绝; - 校验逻辑与生成逻辑脱节,等于白做。



















