測試資料要一批數字、除錯要一個能在服務之間串起來的識別碼、驗版面要一串沒有意義的佔位字元——三種需求都叫「隨機」,但對隨機的要求天差地遠。這個工具用三個分頁分別處理:隨機整數、UUID、隨機字串。關鍵在於三個分頁背後的亂數來源並不一致,而畫面上沒有任何地方提到這件事;它決定了哪一個分頁的輸出可以拿去做什麼,下面會講清楚。
使用步驟
- 上方是三個分頁:「整數」、「UUID」、「字串」。中間那個分頁的標籤在中文與英文介面下都寫作
UUID。 - 「整數」分頁有「最小值」「最大值」「數量 (1–100)」三個數字欄位和一顆「產生」按鈕。按下去之後結果一行一個列在下方,標著「結果」的那一列右邊有複製按鈕,會把整批以換行分隔一次複製走。
- 「UUID」分頁只有一顆「產生 UUID」按鈕,一次給一個,再按一次就把上一個蓋掉。這裡沒有數量欄位,也沒有選版本的地方。
- 「字串」分頁有「長度」與「數量 (1–100)」兩個數字欄位,以及四個字元集勾選框:「數字 (0-9)」「小寫 (a-z)」「大寫 (A-Z)」「特殊符號」。預設勾了前三個、長度 16、數量 5,設定好之後按「產生」。
- 三個分頁都不會自動產生,不按按鈕就不會有結果。在分頁之間切換時各自的結果會留在原地,但重新整理頁面之後全部消失。
什麼時候用得上
造一批測試資料
要一百筆訂單金額、一組年齡欄位、或一串亂序的優先度來測排序邏輯,「整數」分頁設好上下界按一次就有。複製出來是純粹以換行分隔的數字,直接貼進試算表的一欄、SQL 的 VALUES 清單,或測試檔案裡的陣列都很順。
要一個不會撞的識別碼
追 log 用的 correlation ID、避免重複扣款的 idempotency key、寫整合測試時需要一個保證不與既有資料衝突的鍵值——UUID 分頁按一下就有一個標準格式的值,不必為此開一個終端機視窗下 uuidgen。
用佔位字串壓測欄位與版面
想知道使用者名稱欄位塞到 64 個字元會不會撐破卡片、資料庫的 VARCHAR(50) 會不會默默截斷、CSS 的 text-overflow 有沒有真的生效——把長度調到目標值、數量調成 5,產出來的字串沒有語意也沒有空格,正好用來觀察純粹的版面行為。
抽籤、分組與隨機取樣
從編號 1 到 250 的名單裡抽 20 筆做人工抽驗、隨機挑今天要 code review 的檔案序號、把二十個人分成四組——設好範圍與數量按一下就有。要記得它是放回抽樣,重複的號碼得自己處理,理由寫在下面。
限制與注意事項
- 三個分頁其實用了兩種亂數來源,介面上完全沒有標示。「UUID」分頁呼叫的是瀏覽器內建的
crypto.randomUUID;「整數」與「字串」兩個分頁走的是Math.random。實務上的結論很直接:字串分頁產出來的東西不可以拿去當密碼、API 金鑰、session token,也不要放進密碼重設連結裡。 Math.random並不是壞掉的亂數,只是設計目標不同——要快、統計分布要夠均勻,但不需要隱藏內部狀態。以目前 Chrome 與 Node 採用的 xorshift128+ 為例,它的內部狀態只有 128 個位元,觀察到足夠多的輸出就能把狀態解出來,接著往前往後的每一個值都能算得出來。攻擊者拿到你發出去的第一組 token,就有機會推出後面幾組。- 關於 UUID 分頁要講精確一點:程式碼是先檢查
crypto.randomUUID存不存在,存在才呼叫它,不存在時會退回用Math.random拼出一個形狀正確的 v4 字串。這條退路在本站的實際情況下走不到——網站強制導向 HTTPS,而crypto.randomUUID在安全來源下從 Chrome 92、Firefox 95、Safari 15.4 起就都有了。所以正確的說法是「在支援的瀏覽器上取自密碼學等級的來源」,而不是無條件成立的保證。 - 字串的理論強度是上限,不是實得值。預設勾選的三個字元集合起來是 62 個字元,長度 16 的字串理論上約 95 個位元;四個全勾是 88 個字元,約 103 個位元。但底下的
Math.random內部狀態只有 128 個位元,同一批產出來的字串彼此並不獨立,真正的不可預測性遠低於那兩個數字。把它當成「看起來夠亂的佔位字串」,不要當成「103 位元的密鑰」。 - 勾選字元集不保證「每一種至少出現一個」。勾選只是把幾個字元池串成一個大池,然後逐字獨立抽。在預設設定下(62 個字元、長度 16),產出來的字串完全不含數字的機率大約是 6%;四個字元集全勾時,整串都沒有特殊符號的機率大約 0.4%。如果對方系統規定必須同時含數字與符號,產出來的批次裡會有一部分被退件,得自己挑過。
- 整數是放回抽樣,會重複。每一筆都是獨立抽出來的,不是把號碼球拿走的抽籤。用預設值跑一次(1 到 100 抽 10 個),出現至少一組重複號碼的機率大約是 37%——這是生日問題的直接後果,不是程式出錯。
- 夾限發生在按下按鈕的那一刻,而且只夾拿去計算的值。「數量」被夾在 1 到 100、「長度」被夾在 1 到 256,但輸入框裡的數字不會被改寫。所以長度打 1000 再按產生,你會拿到 5 串各 256 個字元的結果,而欄位上仍然寫著 1000。另外有個小陷阱:長度打
0得到的是 8 而不是 1,因為程式的判斷式把0當成「沒填」,於是套用了預設長度。 - 四個數值欄位都以整數解析,小數會被無聲截掉:
5.9讀成 5、2.99讀成 2。用鍵盤上下鍵調整不會產生小數,但直接手打或從別處貼上就會遇到。 - 按了「產生」卻毫無動靜,通常是這三種情況之一:最小值大於最大值、任一數值欄位是空的、或者四個字元集一個都沒勾。這三種情況都會在計算之前被擋下來,而且不會跳出任何錯誤訊息,畫面看起來就像按鈕壞了。先檢查這三件事,多半就找到原因了。
- 整數的算法是「亂數乘上(最大值減最小值加一)取整後再加上最小值」,上下界兩端都包含在內。範圍跨度超過 2^53 時,雙精度浮點數的間隔會大於 1,中間會出現一整片永遠抽不到的數值。日常用不到那麼大的範圍,但如果你打算拿它產生 64 位元的隨機 ID,這裡並不適合。
- 所有的值都是你的瀏覽器當場算出來的,沒有向伺服器要過一個位元,結果也沒有被送到任何地方或留下紀錄。反過來說也成立:離開這一頁就找不回來了,需要的話按下複製再走。這個頁面本身仍會載入廣告等第三方資源,那些連線與你按出來的值毫無關聯。
常見問題
這裡的 UUID 是哪一版?可以直接拿來當資料庫主鍵嗎?
是第 4 版,也就是完全隨機的那一種:128 個位元裡有 6 個固定用來標示版本與變體,剩下 122 個是隨機的,碰撞機率在任何實務規模下都可以忽略。當主鍵在功能上沒問題,但要留意寫入效能:v4 不帶時間順序,連續插入會落在 B-tree 索引的各個角落,造成頁面分裂與快取命中率下降。資料量大的表通常改用有時間前綴的 UUIDv7 或 ULID,那兩種格式這個工具不提供。
可以一次產生 50 個 UUID 嗎?
不行。UUID 分頁只有一顆按鈕,一次一個,新的還會把舊的蓋掉,既沒有數量欄位也不會累積成清單。要一整批的話,在這個頁面上只能按一次複製一次;真的需要量產請在終端機用 uuidgen 之類的指令跑迴圈。旁邊的整數與字串分頁才有數量欄位,上限 100 筆。
我需要一把 API 金鑰,字串分頁夠用嗎?
不夠。正經的金鑰要取自作業系統的密碼學亂數來源:終端機下 openssl rand -hex 32,或在程式裡用 crypto.getRandomValues(瀏覽器與 Node)、secrets.token_urlsafe(Python)、crypto/rand(Go)。這些都直接從作業系統的熵池取值,內部狀態不會外洩給觀察者。至於個人帳號的密碼,交給密碼管理器產生與保存仍然是最省事也最安全的做法。
兩個人同時打開這個頁面,會拿到一樣的隨機值嗎?
不會。每個分頁的亂數產生器都由引擎各自播種,兩台機器、甚至同一台機器上的兩個分頁,序列都不相同。但「不會撞在一起」和「無法被預測」是兩件不同的事:前者成立不代表後者也成立,而安全用途看的正是後者。
為什麼結果裡出現兩個一模一樣的數字?
因為每一筆都是獨立抽的,抽過的號碼會放回去。範圍愈窄、數量愈多,重複就愈明顯:在 1 到 10 之間抽 20 個,依鴿籠原理一定有重複。需要互不相同的清單,實務上的做法是把整個範圍列出來洗牌後取前 N 個,這個工具沒有這個模式,只能自己在試算表裡去重之後再補抽。
「特殊符號」那一組到底包含哪些字元?貼進程式碼會出事嗎?
那一組共 26 個字元:!@#$%^&*()-_=+[]{}|;:,.<>?。裡面包含 <、> 與 &,貼進 HTML 或 XML 屬性時要記得跳脫。這一組刻意不含單引號、雙引號、反斜線、空格與斜線,所以產出來的字串貼進 JSON 字串通常不會直接炸掉;不過 $、!、|、& 在 shell 裡仍然有特殊意義,要當成參數傳的話包在單引號裡比較保險。