<p>PHP 8.2 中 random_* 函数是核心内置功能,非独立扩展;应停用 rand() 等伪随机函数,改用加密安全的 random_int() 或 random_bytes(),并捕获 Random\RandomException。</p>

PHP 8.2 中并没有一个叫“Random扩展”的独立扩展,而是将 random_* 系列函数(如 random_int()、random_bytes())作为核心内置功能直接集成进 PHP 运行时。这些函数自 PHP 7.0 起引入,PHP 8.2 不仅完全支持,还强化了错误处理机制(比如 random_int() 在 CSPRNG 不可用时抛出 Random\RandomException,而非旧版的 Exception)。
所以,“用 Random 扩展替代 rand()” 实际上是:停用 rand() 及其家族(srand、getrandmax),改用 PHP 原生的 random_int() 或 random_bytes() —— 它们不需要额外安装扩展(只要 PHP ≥ 7.0,且系统有可用 CSPRNG 源,现代 Linux/Windows/macOS 均满足)。
直接替换:用 random_int() 替代 rand()
random_int($min, $max) 是最自然、最安全的 rand($min, $max) 替代品:
- ✅ 加密安全(CSPRNG 驱动)
- ✅ 区间闭合(包含
$min和$max,行为与rand()一致) - ✅ 自动处理类型转换(只接受整数,PHP 8.1+ 对参数类型更严格,避免静默截断)
原写法:
立即学习“PHP免费学习笔记(深入)”;
$code = rand(100000, 999999); // 6位验证码
推荐替换为:
try {
$code = random_int(100000, 999999);
} catch (Random\RandomException $e) {
error_log('随机数生成失败: ' . $e->getMessage());
throw new RuntimeException('服务暂时不可用');
}注意:必须捕获 Random\RandomException(不是 Exception 或 Throwable 的泛捕获),否则上线后 CSPRNG 故障会直接导致 500 错误。
为什么不能只换函数名?关键差异要避开
rand()和mt_rand()是伪随机(PRNG),可预测、不抗重放
即使种子不同,同一进程内多次调用仍可能因环境(如容器重启、FPM worker 复用)出现重复值,不适合 token、密码、验证码等场景。random_int()是真随机(基于系统熵源),每次调用独立、不可推导
底层调用/dev/urandom(Linux)、BCryptGenRandom(Windows)等,满足 OWASP 密码学要求。不要手动“模拟” random_int
❌ 错误写法:$n = unpack('V', random_bytes(4))[1] % 100 + 1(取模偏差)
❌ 更错:(int)bin2hex(random_bytes(1)) % 100 + 1(类型混乱 + 偏差)
✅ 正确唯一方式:就用random_int($min, $max)
批量迁移建议:从代码到工具链
搜索替换范围
全局查找:rand(、srand(、getrandmax(,包括大小写变体和空格干扰(如rand ()-
用 PHP-CS-Fixer 自动化(推荐)
启用random_api_migration规则(它默认只升到mt_rand),但注意:该规则不自动升到random_int。你需要:- 先用它清理
rand→mt_rand - 再人工或配合自定义脚本,把明确用于安全场景(如
token、password_reset、api_key相关变量名)的mt_rand替换为random_int
- 先用它清理
-
运行时兜底检测
在项目启动时加一段检查(开发/测试环境):if (function_exists('rand') && !defined('DISABLE_LEGACY_RANDOM')) { trigger_error('detected usage of rand() — forbidden in this codebase', E_USER_WARNING); }
附:非整数需求怎么处理?
-
随机字符串(如 API Token)
用random_bytes()+ 编码:$token = bin2hex(random_bytes(16)); // 32 字符十六进制 // 或 URL 安全 Base64 $token = rtrim(strtr(base64_encode(random_bytes(18)), '+/', '-_'), '=');
-
从数组随机取元素
array_rand()本身不安全(基于mt_rand),应改用:$keys = array_keys($arr); $key = $keys[random_int(0, count($keys) - 1)]; $value = $arr[$key];
-
需要浮点随机数?
PHP 没有random_float()(PHP 8.4 才加入),目前可靠做法是:$float = random_int(0, 999999) / 1000000.0; // 0.000000 ~ 0.999999
不复杂但容易忽略。



















