基礎隨機數:mt_rand() vs random_int()
| 函數 | 特性 | 適用場景 |
| mt_rand() | 梅森旋轉演算法,速度快,**非加密安全** | 遊戲、測試資料、非敏感 ID |
| random_int() | CSPRNG(作業系統熵池),**加密安全**,PHP 7.0+ | Token、密碼、Session ID、API Key |
| random_bytes() | 直接取得隨機位元組,轉 hex/base64 最簡單 | 生成長 Token、CSRF Token |
場景一:簡單數字/字母混合字串(mt_rand)
function genRandomString(int $len = 16, string $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'): string {
$max = strlen($chars) - 1;
$str = '';
for ($i = 0; $i < $len; $i++) {
$str .= $chars[mt_rand(0, $max)];
}
return $str;
}
場景二:加密安全隨機字串(random_int / random_bytes)
方法 A:random_int 逐字元(較慢但直觀)
function genSecureString(int $len = 32, string $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'): string {
$max = strlen($chars) - 1;
$str = '';
for ($i = 0; $i < $len; $i++) {
$str .= $chars[random_int(0, $max)];
}
return $str;
}
方法 B:random_bytes + Base64/HEX(最快、標準)
// 32 位元組 = 256 位熵,Base64 編碼後 43 字元(含 = 補位)
$token = rtrim(base64_encode(random_bytes(32)), '='); // URL-safe 可用 strtr($token, '+/', '-_')
// 或 HEX:64 字元
$token = bin2hex(random_bytes(32));
場景三:高度可自訂的隨機碼生成器(支援類別選擇)
/**
* @param int $length 長度
* @param int $type 字元集類型:
* 0 = 數字+大寫 (預設)
* 1 = 純數字
* 2 = 小寫字母
* 3 = 大寫字母
* 4 = 特殊符號
* -1 = 所有類型混合
* @param bool $secure 是否使用 CSPRNG
*/
function randCode(int $length = 8, int $type = 0, bool $secure = false): string {
$sets = [
1 => '0123456789',
2 => 'abcdefghijklmnopqrstuvwxyz',
3 => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
4 => '~@#$%^&*()_+-=[]{}|;:,.<>?',
];
if ($type === 0) unset($sets[4]); // 預設不含特殊符號
elseif ($type === -1) ; // 全部
else $sets = [$type => $sets[$type]];
$pool = implode('', $sets);
$max = strlen($pool) - 1;
$fn = $secure ? 'random_int' : 'mt_rand';
$str = '';
for ($i = 0; $i < $length; $i++) {
$str .= $pool[$fn(0, $max)];
}
return $str;
}
// 使用
echo randCode(6, 1); // 6 位數字驗證碼
echo randCode(12, -1, true); // 12 位強密碼(含特殊符號,CSPRNG)
場景四:密碼生成最佳實踐(符合 OWASP 建議)
function generatePassword(int $length = 16): string {
// 確保至少包含:大寫、小寫、數字、特殊符號
$upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$lower = 'abcdefghijklmnopqrstuvwxyz';
$digits = '0123456789';
$special = '!@#$%^&*_-+=';
$all = $upper . $lower . $digits . $special;
$pwd = '';
$pwd .= $upper[random_int(0, strlen($upper)-1)];
$pwd .= $lower[random_int(0, strlen($lower)-1)];
$pwd .= $digits[random_int(0, strlen($digits)-1)];
$pwd .= $special[random_int(0, strlen($special)-1)];
for ($i = 4; $i < $length; $i++) {
$pwd .= $all[random_int(0, strlen($all)-1)];
}
// 打亂順序
return str_shuffle($pwd);
}
效能與安全總結
- **非敏感場景**(檔名、測試資料、遊戲):`mt_rand` + 自訂字元集,效能最佳。
- **敏感場景**(API Token、重設密碼連結、Session ID、加密金鑰):**必須用 `random_bytes` / `random_int`**。
- **唯一 ID**:`bin2hex(random_bytes(16))` (32 字元) 或 `uniqid('', true)`(含微秒,但熵較低)。
- **避免**:`rand()`(已棄用)、`shuffle()` 非加密、`time()` 可預測。