JavaScript 產生的 UUID 是一個 128 位元的識別碼,以 32 個十六進位數字寫成標準的 8-4-4-4-12 格式 — 例如 f47ac10b-58cc-4372-a567-0e02b2c3d479 — 其中第 13 個十六進位數字固定為 4(版本),第 17 個則固定為 8、9、a 或 b(變體),所以 128 個位元中有 6 個是保留的,剩下 122 個可作為隨機之用。正是這 122 位元的承載量,讓 UUID v4 在任何實際應用程式產生的數量下幾乎不會碰撞。在 JavaScript 中,填入那 122 位元的安全做法是使用 Web Crypto API 的 crypto.getRandomValues,它會從瀏覽器的密碼學安全隨機數產生器取值。簡寫「UUID」代表 Universally Unique IDentifier(通用唯一識別碼),v4 變體則是 RFC 4122 及其 2024 年取代文件 RFC 9562 所定義的完全隨機版本 — 這是一種可以在任何裝置、任何地點獨立產生,不需連線至中央註冊機制的識別碼。這種無需協調的特性,正是為何這麼多 JavaScript 技術堆疊預設採用 v4 作為資料庫鍵、冪等權杖、日誌關聯 ID 與檔案名稱的原因。

how to generate uuid in javascript
how to generate uuid in javascript

UUID v4 實際上看起來是什麼樣子

每個 v4 UUID 是一個 128 位元的值,以 32 個十六進位字元呈現,分成五個區塊,長度依序為 8、4、4、4 與 12 個字元,以連字號分隔。因此標準的文字形式長度為 36 個字元 — 32 個十六進位數字加上 4 個連字號。在這 128 個位元中,正好有 6 個是非隨機的:4 個位元用於編碼版本,2 個位元用於編碼變體。由於 v4 將版本 4 儲存在第 13 個十六進位數字的高位半位元組,該數字永遠是字面字元 4。變體位元則位於第 17 個十六進位數字的高兩位元,因此該數字永遠是 8、9、a 或 b 其中之一。任何人都可以透過掃描這兩個位置來辨識 v4 UUID — 這就是整個規格的識別特徵。

辨識出版本與變體,也能讓你一眼區分 v4 與其他 UUID 版本。第 13 個十六進位數字依版本編碼為 1、3、4、5 或 7;第 17 位數字的規則則適用於所有版本,因為變體欄位是共用的。連字號分組的形狀、固定的版本半位元組,以及固定的變體半位元組,共同定義了在程式碼審查、日誌管線或資料庫欄位限制中,「看起來像 v4」真正的意涵。

為何隨機來源在 JavaScript 中至關重要

v4 UUID 中的 122 個隨機位元必須有來源,而這個來源非常重要。一段簡短的 JavaScript 程式碼可以呼叫 Math.random() 並格式化輸出,產生一個看起來像 UUID 的字串,但 Math.random 並不具備密碼學安全性:它的決定性高到足以讓看過幾次輸出的攻擊者,有時能預測後續輸出,而且其演算法在不同的引擎間也有所差異。瀏覽器安全的方式是 crypto.getRandomValues,它取自驅動 TLS 交握及其他安全關鍵 API 的同一個 CSPRNG。

這正是UUID 產生器所產生的識別碼能安全暴露於 URL、日誌與用戶端程式碼的核心原因:每個值都是從你分頁內的 crypto.getRandomValues 所產生。透過從 CSPRNG 取出 122 個位元,每個輸出在統計上都與前一個輸出獨立 — 沒有共用種子、沒有時鐘、沒有 MAC 位址,也沒有混入命名空間。這項特性讓兩個無關的服務即使在同一瞬間產生 ID,仍能確信不會發生碰撞。跳過 CSPRNG 的代價不只是理論上的:可預測的識別碼可能會被猜測、重送或在多個請求間建立關聯,這正是安全審查在拒絕基於弱隨機性所建立的識別碼時,所標記的失敗模式。

在瀏覽器中產生 UUID

不寫任何一行程式碼,就能快速產生單一 UUID 或一批 UUID 的方法,就是使用瀏覽器內的 UUID 產生器。整個流程在本地端執行,因此在發生任何網路往返之前,識別碼就已就緒。

  1. 開啟 UUID 產生器,輸入你想要的 UUID 數量,從 1 到 100。
  2. 如果你的資料庫欄位或程式碼風格需要不同的文字形式,可以切換uppercase(大寫)來將十六進位數字大寫,或切換remove hyphens(移除連字號)來移除四個分隔符號,產生一串連續的 32 字元字串。
  3. 點擊Generate(產生)。清單會重新整理,顯示從你瀏覽器的 CSPRNG 取得的全新 v4 UUID。
  4. 將游標懸停在任何一列上即可複製該單一 UUID,或使用Copy all(全部複製)一次取得整批 UUID 至剪貼簿。

由於此工具在你的分頁中執行,你可以無限重複這個步驟:每次點擊 Generate 都會產生全新的批次,而且你可以在多次執行間變更格式切換,而不會遺失先前產生的值。對於也想在實際程式碼中測試這些值的開發者來說,JavaScript Playground 是一個有用的輔助工具 — 將產生的 UUID 貼到程式碼片段中,在出貨前對你實際的驗證邏輯進行測試。

選擇輸出格式

三個切換選項決定了 UUID 產生器所回傳的文字形式。它們都不會改變底層 128 位元的值,所以選擇純粹取決於你的下游系統需要什麼。

切換選項文字形式範例值相同嗎?
預設小寫,含連字號f47ac10b-58cc-4372-a567-0e02b2c3d479是
大寫大寫十六進位,含連字號F47AC10B-58CC-4372-A567-0E02B2C3D479是
無連字號小寫,無分隔符號f47ac10b58cc4372a5670e02b2c3d479是
兩者皆是大寫十六進位,無分隔符號F47AC10B58CC4372A5670E02B2C3D479是

資料庫欄位通常儲存標準的 36 字元形式,因為它符合規格,但部分權杖系統、標頭值與嵌入式識別碼偏好 32 字元的無連字號形式,以節省空間或符合固定寬度欄位。如果你的技術堆疊以不區分大小寫的方式比較 UUID,大寫選項無妨;如果是以區分大小寫的方式比較,則請堅持使用小寫,才不會讓兩個看起來不同、實際上卻代表相同識別碼的字串造成困擾。

UUID v4 適用的時機

版本 4 是任何需要由兩個系統獨立產生、無需協調之識別碼的正確預設選擇 — 這正是 JavaScript 開發者經常面臨的情境。

UUID 版本位元來源典型的 JavaScript 使用案例
v1時間戳記 + MAC 位址在 JS 中很少使用;可能洩漏主機資訊
v3命名空間 + 名稱的 MD5 雜湊從已知輸入產生的決定性 ID
v4來自 CSPRNG 的 122 個隨機位元資料庫鍵、冪等權杖、追蹤 ID、檔案名稱
v5命名空間 + 名稱的 SHA-1 雜湊與 v3 相同,但使用更強的雜湊
v7毫秒時間戳記 + 隨機尾碼用於索引局部性的時間排序鍵

實際案例與 v4 完全吻合:需要在同步前先建立記錄的分散式與離線優先系統、可防止重複 API 呼叫的冪等鍵、能貫穿整個日誌管線的關聯 ID,以及在跨服務時絕不能碰撞的物件或檔案名稱。對這些用途而言,完全沒有任何時鐘、MAC 位址或命名空間輸入,正是一項優點 — 沒有任何東西會洩漏,也沒有任何東西需要協調。

值得特別提出的一個例外是 UUIDv7。如果你的資料庫以主鍵建立索引,而且你在意索引的局部性 — 也就是新寫入的資料總是落在索引末端附近,而不是隨機分散 — 那麼 v7 的時間排序前綴會是更好的選擇。對於無序的唯一性(這是常見情況),v4 仍然是預設。

純瀏覽器產生與安全性

產生器所產生的每個 UUID,都是使用 crypto.getRandomValues 在你的瀏覽器分頁中於本地端計算。你所產生或複製的內容都不會傳送至伺服器,因此這個工具無論是用於正式環境的識別碼或內部機密都安全無虞。這項保證來自於實作本身,而不是來自於隱私承諾:此頁面從未對 UUID 後端開啟任何網路連線,剪貼簿的輸出是該值唯一會前往的地方。

為了讓碰撞的數學更具體,請考慮 122 個隨機位元。生日界限 — 即一組數字中至少出現一次重複的機率達到 50% 的門檻 — 大約是 2.71 × 10^18。將其除以每秒 10^9 個 UUID,再除以每年 31,536,000 秒,你就會得到大約 86 年的持續產生時間(每秒十億個 UUID 的速率),才會讓單一重複的可能性超過 50%。這正是分散式系統在無需跨機器協調的情況下,將 v4 UUID 視為實際上唯一的原因,也正是讓它們能在瀏覽器分頁中安全產生的特性。

對 JavaScript 開發者而言,實用的結論很簡短。任何需要無法被猜測的識別碼時,請跳過 Math.random()。在程式碼中使用 crypto.getRandomValues(),並在你需要一個比寫程式片段更快的值時,使用 UUID 產生器 — 輸出是相同的 122 位元隨機識別碼,只是不需要網路往返就能產生。如果需要驗證規格細節,標準參考文件是 RFC 4122,已由 RFC 9562 更新,其中精確定義了版本與變體位元的設定方式。

如果你正在權衡各種選項,如何使用 JavaScript 按鍵碼查詢工具對此有詳細說明。