隨機字符串廣泛用於:API Token、密碼重置鏈接、訂單號、驗證碼、Session ID、CSRF Token 等安全敏感場景。PHP 提供了多種生成方式,選擇正確的方法關係到業務安全性。
| 方法 | 適用場景 | 安全性 | 性能 |
|---|---|---|---|
rand()/mt_rand() | 非安全場景(顏色、測試數據) | 低(可預測) | 高 |
uniqid() | 唯一標識(微秒級) | 中(可暴力破解) | 高 |
openssl_random_pseudo_bytes() | 加密級 Token、密鑰 | 高(CSPRNG) | 中 |
random_bytes() (PHP 7+) | 現代加密級首選 | 極高 | 中 |
random_int() (PHP 7+) | 安全整數範圍 | 極高 | 中 |
str_shuffle() | 簡單打亂字符集 | 低 | 高 |
<?php
/**
* 隨機字符串生成器
* 支持多種字符集模式,PHP 7+ 自動使用 CSPRNG
*/
class RandomStringGenerator
{
// 預定義字符集常量
const MODE_NUMERIC = 1; // 0-9
const MODE_LOWER = 2; // a-z
const MODE_UPPER = 3; // A-Z
const MODE_ALPHA = 4; // A-Z a-z
const MODE_ALPHANUMERIC = 0; // A-Z a-z 0-9 (默認)
const MODE_UPPER_NUM = 5; // A-Z 0-9
const MODE_LOWER_NUM = 6; // a-z 0-9
const MODE_HEX = 7; // 0-9 a-f
const MODE_BASE64 = 8; // A-Z a-z 0-9 + /
private static $charsets = [
self::MODE_NUMERIC => '0123456789',
self::MODE_LOWER => 'abcdefghijklmnopqrstuvwxyz',
self::MODE_UPPER => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
self::MODE_ALPHA => 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
self::MODE_ALPHANUMERIC => 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
self::MODE_UPPER_NUM => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789',
self::MODE_LOWER_NUM => 'abcdefghijklmnopqrstuvwxyz0123456789',
self::MODE_HEX => '0123456789abcdef',
self::MODE_BASE64 => 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
];
/**
* 生成隨機字符串
* @param int $length 長度
* @param int $mode 字符集模式
* @param bool $crypto 是否強制使用加密級隨機源
* @return string
* @throws Exception 長度非法或模式不存在
*/
public static function generate(int $length = 32, int $mode = self::MODE_ALPHANUMERIC, bool $crypto = false): string
{
if ($length <= 0) {
throw new InvalidArgumentException('Length must be positive');
}
if (!isset(self::$charsets[$mode])) {
throw new InvalidArgumentException("Invalid mode: {$mode}");
}
$charset = self::$charsets[$mode];
$maxIndex = strlen($charset) - 1;
$result = '';
if ($crypto || $mode === self::MODE_BASE64) { // Base64 常用於 Token,建議加密級
// PHP 7+ random_bytes 每次生成多字節,效率更高
$bytes = random_bytes($length);
for ($i = 0; $i < $length; $i++) {
$result .= $charset[$bytes[$i] % ($maxIndex + 1)];
}
} else {
// 兼容 PHP 5.6:mt_rand 非加密級但速度快
for ($i = 0; $i < $length; $i++) {
$result .= $charset[mt_rand(0, $maxIndex)];
}
}
return $result;
}
// 便捷靜態方法
public static function numeric(int $len = 6): string { return self::generate($len, self::MODE_NUMERIC); }
public static function alphaNumeric(int $len = 32): string { return self::generate($len, self::MODE_ALPHANUMERIC); }
public static function token(int $len = 32): string { return self::generate($len, self::MODE_BASE64, true); }
public static function hex(int $len = 32): string { return self::generate($len, self::MODE_HEX); }
}
require_once 'RandomStringGenerator.php';
use RandomStringGenerator as RSG;
// 1. 6 位數字驗證碼
$smsCode = RSG::numeric(6); // e.g. "839201"
// 2. 32 位 API Token(加密級)
$apiToken = RSG::token(32); // e.g. "K7m9Xp2Q... (Base64 charset)"
// 3. 16 位十六進制字符串(如 MD5 片段)
$hexStr = RSG::hex(16);
// 4. 自定義:20 位大寫字母+數字(優惠碼風格)
$coupon = RSG::generate(20, RSG::MODE_UPPER_NUM); // e.g. "A3F9K2..."
// 5. 兼容舊代碼調用方式
$legacy = (new RSG())->generate(16, 0); // 實例調用也支持
random_bytes / openssl_random_pseudo_bytes),否則面臨預測攻擊風險。time()、microtime()、uniqid() 作為安全 Token 來源,它們熵極低。0/O, 1/l/I),生成人工錄入的驗證碼/優惠碼時尤為重要。random_bytes($n * $length) 後切片,減少系統調用開銷。mt_rand。[] 最後 implode())。本文提供的 RandomStringGenerator 類已在多個生產項目中穩定運行,涵蓋從簡單驗證碼到金融級 API 簽名的各類場景,建議直接納入項目公共庫。