首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Discuz! X1.5 隨機數函數 random() 源碼分析:基於 microtime+DocumentRoot 的種子生成策略

     編輯:PHP 相關知識

Discuz! X1.5 隨機數函數 random() 源碼分析:基於 microtime+DocumentRoot 的種子生成策略

Discuz! 經典隨機數函數 random($length, $numeric) 採用獨特的種子構造方式,結合 microtime() 與 $_SERVER['DOCUMENT_ROOT'] 生成偽隨機字串。本文深度解析其演算法流程與特性。

源碼還原

function random($length, $numeric = 0) {
    // 1. 種子材料:微秒時間 + 文檔根目錄
    $seed = base_convert(md5(microtime() . $_SERVER['DOCUMENT_ROOT']), 16, $numeric ? 10 : 35);
    
    // 2. 字元池構建
    if ($numeric) {
        // 純數字模式:移除 0 並補充 012340567890
        $seed = str_replace('0', '', $seed) . '012340567890';
    } else {
        // 混合模式:原種子 + zZ + 大寫版
        $seed = $seed . 'zZ' . strtoupper($seed);
    }
    
    // 3. 隨機抽取
    $hash = '';
    $max = strlen($seed) - 1;
    for ($i = 0; $i < $length; $i++) {
        $hash .= $seed{mt_rand(0, $max)};
    }
    return $hash;
}

// 測試
echo random(15, 1) . "<br>"; // 純數字
echo random(15);                // 混合字母數字

執行結果示例

228283270677112
SjqffsU76994qfS

演算法逐步解析

步驟代碼目的
種子材料microtime() . $_SERVER['DOCUMENT_ROOT']引入高熵時間 + 固定環境變量,增加不可預測性
MD5 雜湊md5(...)將任意長度輸入壓縮為 32 字元十六進位
進制轉換base_convert(..., 16, 35/10)數字模式轉 10 進制(0-9);混合模式轉 35 進制(0-9, a-z)
字元池擴充str_replace('0','') . '012340567890 / . 'zZ' . strtoupper()確保字元池包含足夠多樣性,避免 base_convert 輸出字元集過窄
隨機抽樣$seed{mt_rand(0,$max)}從字元池有放回抽樣

安全性評估

  • ⚠️ 非加密安全:mt_rand() 為梅森旋轉演算法,可預測;種子含 DOCUMENT_ROOT 固定值,熵來源有限。
  • ⚠️ 不適用於:Session ID、Token、加密金鑰、密碼重設連結等安全敏感場景。
  • ✅ 適用於:臨時文件名、非敏感唯一標識、測試數據生成、遊戲隨機事件。

現代替代方案

// PHP 7+ 加密安全隨機字串
function random_secure($length, $numeric = false) {
    $bytes = random_bytes(ceil($length / 2));
    $pool = $numeric ? '0123456789' : '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $result = '';
    for ($i=0; $i<$length; $i++) {
        $result .= $pool[random_int(0, strlen($pool)-1)];
    }
    return $result;
}

// 或使用 bin2hex(random_bytes($n)) 獲取十六進位隨機串

Discuz! random() 是「工程妥協」的典型產物:在 PHP 早期缺乏 random_bytes() 時,以可用性換取開發效率。理解其局限,才能在正確場景做正確選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved