🔐
← 返回教學列表

Base64 URL 安全編碼:它是什麼以及為什麼重要

· 標籤: base64, url-safe, base64url, jwt, encoding, web-development, api

什麼是 Base64 URL 安全編碼?

Base64 URL 安全編碼(也稱為 Base64url)是標準 Base64 的變體,它將在 URL 和檔案名稱中具有特殊意義的字元替換為安全的替代字元。標準 Base64 使用 +/ 作為其 64 字元字元集的一部分,再加上 = 作為填充,而這三個字元在 URL、查詢字串和檔案路徑中都會造成問題。

Base64url 透過兩個簡單的替換解決了這個問題:

| 標準 Base64 | URL 安全 Base64 | |-----------------|-----------------| | +(加號) | -(減號) | | /(斜線) | _(底線) | | =(填充) | 省略(通常) |

為什麼標準 Base64 會破壞 URL

當包含 +/ 的 Base64 編碼字串出現在 URL 中時,瀏覽器和伺服器的行為會變得不可預測。

+ 的問題

在 URL 查詢字串中,+ 字元被解讀為空格。這一行為源自 application/x-www-form-urlencoded 規範,會導致解碼後的資料中包含非預期的空格。

例如,像 Pj4+Pz8/Pw== 這樣的 Base64 字串包含 + 字元。如果它出現在 URL 參數 ?token=Pj4+Pz8/Pw== 中,伺服器會收到 ?token=Pj4 Pz8/Pw==——+ 變成了空格。

/ 的問題

在 URL 路徑中,/ 字元是路徑分隔符號。像 ab/CD+Ef== 這樣的 Base64 字串包含的 / 會被解讀為目錄層級。如果它出現在 URL 區段中,客戶端和伺服器都可能誤解其結構。

= 的問題

= 字元在查詢字串中用於鍵值對。?data=SGVsbG8= 中的尾隨 = 可能產生歧義——這個 = 是 Base64 填充的一部分,還是查詢參數語法的一部分?

雖然百分比編碼可以解決這些問題(+ 變成 %2B/ 變成 %2F),但它會增加字串長度並讓除錯更加困難。Base64url 是更簡潔的解決方案。

Base64url 的運作方式

Base64url 正式定義於 RFC 4648 第 5 節。它使用與標準 Base64 完全相同的演算法——3 位元組變成 4 個字元——但在字元集的位置 62 和 63 處進行了單字元替換:

  • 字元集索引 62:+-(減號)
  • 字元集索引 63:/_(底線)

填充(=)通常會被移除,因為解碼時可以從字串長度推斷出來。Base64url 字串始終是有效的 URL 組成部分,無需額外的跳脫處理。

轉換前後對照

以下是相同二進位資料在兩種格式中的樣貌:

標準:    Pj4+Pz8/Pw==
URL 安全:Pj4-Pz8_Pw

Base64url 的應用場景

JSON Web Token(JWT)

JWT 是 Base64url 最顯著的使用者。每個 JWT 由三個部分組成——標頭(header)、酬載(payload)和簽章(signature)——每個部分都經過 URL 安全 Base64 編碼並以點號分隔:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNqP0m2iTgCjD0

請注意其中的減號和底線——沒有加號或斜線。如果 JWT 使用標準 Base64,當 Token 作為 URL 參數傳遞時(這是它們在網頁應用程式中最常見的使用方式)就會失效。

OAuth 和 OpenID Connect

OAuth 2.0 和 OpenID Connect 都依賴 JWT 來處理存取 Token 和 ID Token,這使得 Base64url 編碼成為現代身分驗證的基礎。授權碼流程、隱式流程和客戶端憑證流程都會傳輸使用 Base64url 的 Token。

Web API 和查詢參數

許多 REST 和 GraphQL API 在查詢參數中接受 Base64 編碼的資料,用於分頁游標、篩選器或編碼的酬載。Base64url 確保這些參數能正確運作,無需額外的 URL 編碼。

實際案例——API 游標分頁:

GET /api/users?cursor=MjAyNC0wMS0xNVQxMDozMDowMFo

GitHub 的 API 就使用這種模式來對大型結果集進行分頁。

檔案名稱與檔案儲存

Base64url 字串可以作為安全的檔案名稱,因為它們不包含路徑分隔符號(/)、不會混淆檔案系統的特殊字元,也不包含在 Windows 上無效的字元(:*? 等)。

內容傳遞網路和快取鍵

CDN 和快取層通常使用 Base64url 編碼的值作為快取鍵。使用標準 Base64 時,/ 會在快取命名空間中建立虛假的目錄層級結構,導致鍵值模糊不清。

在標準 Base64 和 Base64url 之間轉換

在兩種變體之間進行轉換在任何語言中都很直接:

JavaScript

// Standard Base64 to URL-safe Base64
function base64ToBase64url(base64) {
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
}

// URL-safe Base64 to Standard Base64
function base64urlToBase64(base64url) {
  let result = base64url.replace(/-/g, '+').replace(/_/g, '/');
  // Restore padding
  while (result.length % 4) {
    result += '=';
  }
  return result;
}

Node.js

Node.js 自 15.7.0 版本起提供原生的 Base64url 支援:

// Encode to Base64url
const encodedUrl = Buffer.from('Hello, world!').toString('base64url');
console.log(encodedUrl);
// Output: SGVsbG8sIHdvcmxkIQ

// Decode from Base64url
const decoded = Buffer.from(encodedUrl, 'base64url').toString('utf-8');
console.log(decoded);
// Output: Hello, world!

Python

import base64

# Encode to Base64url
encoded = base64.urlsafe_b64encode(b"Hello, world!")
print(encoded.decode())
# Output: SGVsbG8sIHdvcmxkIQ==

# Decode from Base64url
decoded = base64.urlsafe_b64decode(encoded)
print(decoded.decode())
# Output: Hello, world!

何時使用標準 Base64 vs Base64url

使用標準 Base64 的情境:

  • 編碼電子郵件附件(MIME 標準要求)
  • 生成用於 HTML/CSS 嵌入的 Data URL
  • 將資料儲存在不需要 URL 安全性的資料庫中
  • 與預期標準 Base64 的舊版系統互動

使用 Base64url 的情境:

  • 建立或解析 JWT Token
  • 在 URL 查詢參數或路徑區段中傳遞編碼資料
  • 從二進位資料生成檔案名稱
  • 建立快取鍵或識別碼
  • 使用 OAuth Token 或 OpenID Connect

線上試用 Base64 URL 安全編碼

使用我們的免費線上 Base64 編碼器和解碼器在標準 Base64 和 URL 安全 Base64 格式之間進行轉換。貼上您的資料,選擇您要的變體,立即獲得結果。