php 7.0+ 应用 random_bytes() 生成密码学安全随机字符串,需 bin2hex() 或 base64_encode() 转换二进制结果,避免直接使用或忽略异常;uniqid() 不安全,仅适用于非敏感场景。

用 random_bytes() 生成真正安全的随机字符串
PHP 7.0+ 推荐用 random_bytes(),它基于操作系统的加密随机源(如 /dev/urandom 或 CryptGenRandom),能防预测、适合生成 token、密码重置码等。别再用 mt_rand() 拼接——它不安全,且结果可被推断。
常见错误:直接把 random_bytes() 返回的二进制当字符串用,导致乱码或截断;或没处理异常,服务在无 CSPRNG 环境下直接崩。
-
random_bytes()返回的是二进制字节串,需用bin2hex()或base64_encode()转成可读字符串 - 长度参数必须是正整数,传
0会抛Exception;传负数会触发警告并返回空 - 若环境不支持(极少见,如某些 chroot 或旧容器),会抛
Exception,建议包裹try/catch - 示例:生成 16 字节(32 位 hex)的随机字符串:
$token = bin2hex(random_bytes(16));
uniqid() 不是随机函数,慎用于安全场景
uniqid() 本质是微秒级时间戳 + 可选前缀,**不是随机数生成器**。它输出可预测、无熵、易被暴力枚举,只适合生成临时文件名、日志 ID 这类不要求不可猜测的标识符。
常见错误:用 uniqid('', true) 就以为“加了熵就安全”,其实那个额外熵只是进程 ID 和微秒,对攻击者几乎不构成障碍。
立即学习“PHP免费学习笔记(深入)”;
-
uniqid('', true)的第二参数只是追加了microtime()和getmypid(),仍属确定性输出 - 即使加盐(如
uniqid('prefix_', true)),也无法提升密码学安全性 - 性能上它极快,但代价是零安全性;和
random_bytes()完全不是同一用途 - 示例(仅限非敏感用途):
$tmpName = uniqid('upload_', true); // 如 upload_65f3a1b2c8e9d7.12345678
兼容老版本 PHP(
PHP 5.6 及更早没 random_bytes(),也不能依赖 mcrypt_create_iv()(已废弃且部分系统禁用)。这时唯一靠谱的选择是 openssl_random_pseudo_bytes(),但要注意它的返回值真假和强弱标志。
常见错误:忽略第二个参数 $crypto_strong,误以为只要不报错就一定安全;或没检查返回值是否为 false(如 OpenSSL 扩展未启用)。
- 必须传引用变量接收
$crypto_strong,否则无法判断是否真随机 - 若
$crypto_strong === false,说明系统无法提供密码学安全随机数,应中止流程或降级处理(不推荐) - 返回
false时不会抛异常,容易静默失败 - 示例(带校验):
$bytes = openssl_random_pseudo_bytes(16, $strong); if ($bytes === false || $strong === false) { throw new Exception('Unable to generate secure random bytes'); } $token = bin2hex($bytes);
字符集与长度:别让 base64 或 hex 坑了你
用 bin2hex() 得到的是 0–9+a–f,长度翻倍;用 base64_encode() 含 +、/、=,可能在 URL 或文件名中出问题。选哪种,得看使用场景。
常见错误:直接用 base64_encode(random_bytes(12)) 生成 token 放 URL,结果 + 被当成空格解码,/ 导致路由 404。
- URL/文件名安全:用
base64_url_encode()(PHP 7.0+)或手动替换:$safe = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($bytes));
- 数据库或 API 字段:hex 更稳妥,无特殊字符,排序也友好
- 长度计算要对应:16 字节 → hex 是 32 字符,base64 是 24 字符(无填充)
- 别为了“看起来更随机”而用
str_shuffle()处理结果——它破坏熵,还可能引入偏差
uniqid() 当安全函数用。这几个地方一松动,token 就可能批量失效或被撞库。











