应使用 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 位字符串Exception,建议简单包裹 try/catch
避免可读性差的符号(如 !@#$%)导致用户输入错误或 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 字符串中提前剔除,而不是事后过滤如果场景允许使用符号(例如后端服务间认证),可扩展字符集,但注意 URL 安全性和 Shell 解析风险。
base64_encode(random_bytes(18)) 得到 2
+、/、=),但需替换为 URL 安全变体:strtr($s, '+/', '-_')
.-_~),确保总字符数仍是 2⁸ 的约数(如 64),否则模偏差会变大openssl_random_pseudo_bytes() —— 已废弃,且旧版本可能 fallback 到非安全模式真正要注意的不是“怎么拼出一串字符”,而是“每个字符是否独立、均匀、不可预测”。哪怕只漏掉一次 try/catch 或误用 rand(),整个密码机制就形同虚设。