应使用 random_bytes() 生成密码学安全随机字节,再映射为大小写字母加数字的字符串;避免 rand() 或 mt_rand(),因其不安全;12位密码熵值约71 bit,兼顾安全性与可用性。

PHP 生成安全随机密码,别用 rand() 或 mt_rand() 拼字符串 —— 它们不满足密码学安全要求,容易被预测。
用 random_bytes() 生成真正随机字节
这是 PHP 7+ 提供的密码学安全随机数生成函数,底层调用操作系统 CSPRNG(如 /dev/urandom 或 CryptGenRandom),适合生成密钥、token、密码等敏感值。
- 必须配合
bin2hex()、base64_encode()或自定义字符映射使用,因为random_bytes()返回的是二进制数据,不能直接当密码用 - 长度参数传的是字节数,不是最终密码字符数;比如
random_bytes(16)→ hex 后是 32 位字符串 - 若发生系统 RNG 不可用(极罕见),会抛出
Exception,建议简单包裹try/catch
生成含大小写字母 + 数字的 12 位密码
避免可读性差的符号(如 !@#$%)导致用户输入错误或 URL 编码问题,同时保证熵值足够(12 位 × log₂(62) ≈ 71 bit)。
function generatePassword($length = 12) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$bytes = random_bytes($length);
$password = '';
for ($i = 0; $i < $length; $i++) {
$password .= $chars[$bytes[$i] % strlen($chars)];
}
return $password;
}
- 这里用
$bytes[$i] % strlen($chars)是安全的模运算:即使$bytes值很大,分布仍近似均匀(偏差可忽略) - 不要用
str_shuffle(str_repeat($chars, 5))+substr()——str_shuffle()基于rand(),不安全 - 若需排除易混淆字符(如
0O1lI),应在$chars字符串中提前剔除,而不是事后过滤
生成带符号的密码(如用于 API Key)
如果场景允许使用符号(例如后端服务间认证),可扩展字符集,但注意 URL 安全性和 Shell 解析风险。
立即学习“PHP免费学习笔记(深入)”;
- 推荐用
base64_encode(random_bytes(18))得到 24 字符 Base64 字符串(含+、/、=),但需替换为 URL 安全变体:strtr($s, '+/', '-_') - 若坚持用自定义符号集(如
.-_~),确保总字符数仍是 2⁸ 的约数(如 64),否则模偏差会变大 - 避免使用
openssl_random_pseudo_bytes()—— 已废弃,且旧版本可能 fallback 到非安全模式
真正要注意的不是“怎么拼出一串字符”,而是“每个字符是否独立、均匀、不可预测”。哪怕只漏掉一次 try/catch 或误用 rand(),整个密码机制就形同虚设。











