Base64 與 URL 編碼都是「讓資料能安全地以文字傳遞」的工具,所以很容易搞混。但它們解決的是不同問題。以下說明差別。
同一段文字,兩種編碼,並排看。 我們把
台北 101分別丟進兩個工具。Base64 給5Y+w5YyXIDEwMQ==;URL 編碼 給%E5%8F%B0%E5%8C%97%20101。兩者的起點是同樣那 10 個 UTF-8 位元組,接著就完全分岔:Base64 把所有位元組重新用 64 個字元的字母表表示,並補齊到 4 的倍數(所以有==);百分比編碼則讓1、0、1這種安全字元原樣留著,只轉義其餘的。這就是為什麼 Base64 一律膨脹三分之一,而 URL 編碼只膨脹該膨脹的部分。
Base64:二進位 → 文字
Base64 把任何二進位資料(圖片、檔案、原始位元組)變成純 ASCII 的字母、數字、+、/、=。它會讓資料變大約 33%,而且不是加密——誰都能解回來。當只能走純文字的通道卻要帶二進位時使用:
- 把圖片以
data:URI 嵌進 HTML/CSS - 電子郵件附件(MIME)
- 把小型二進位塞進 JSON 或權杖
延伸見 Base64 是加密嗎?(劇透:不是)。
URL 編碼:讓文字能安全放進網址
URL 編碼(又稱百分比編碼)把在網址裡有特殊意義或不允許的字元換成 %XX——空格變 %20、& 變 %26,以此類推。當要把文字放進以下位置時使用:
- 查詢字串(
?q=hello%20world) - 路徑片段
- 表單送出
細節見 URL 編碼指南。
一眼看懂差異
- 目的:Base64 = 用文字帶二進位 · URL 編碼 = 讓文字能安全放進網址。
- 輸出:Base64 = A–Z a–z 0–9 + / = · URL 編碼 = 原文字加上
%XX轉義。 - 大小:Base64 ≈ +33% · URL 編碼只讓被轉義的字元變長。
這兩套做法差最多的地方是非 ASCII 的輸入,而且差多少是量得出來的。台北 是六個 UTF-8 位元組。Base64 把這六個位元組變成 5Y+w5YyX —— 八個字元。百分號編碼把同樣的六個位元組變成 %E5%8F%B0%E5%8C%97 —— 十八個字元,每個位元組三個,因為每一個位元組都要寫成一個 % 加兩位十六進位。Base64 明顯精簡得多;但它在網址列上完全不可讀,而那正是網址選另一套的原因。
兩者常搭配使用
Base64 字串可能含 +、/、=,這些在網址裡不安全——所以若要把 Base64 放進網址,要嘛再做 URL 編碼,要嘛用 Base64URL(用 - 和 _ 的網址安全變體)。
兩個都試試(本機)
- Base64 編解碼——二進位/文字 ⇄ Base64。
- URL 編解碼——把文字做百分比編碼給網址用。
原則:Base64 用來以文字承載二進位;URL 編碼用來把文字安全放進連結。
實際範例
拿文字 a b&c 來看,兩種編碼的處理方式完全不同:
輸入: a b&c
URL 編碼: a%20b%26c
Base64 編碼: YSBiJmM=
URL 編碼不動英文字母,只把空格與 & 轉義,所以結果還看得懂。Base64 則把每一個位元組改寫進它自己的字母表(每 3 個位元組換成 4 個字元),輸出跟原文完全不像——但它現在能通過只容許少數安全字元的通道。任務不同,輸出自然不同。
填充是看起來最沒道理的部分,而只要把四種長度的輸入排在一起,它就不再沒道理了。Base64 每吃三個位元組吐出四個字元;最後一組不滿三個時,= 就是用來記「差多少」的。下表每一列都是我們自己的 Base64 編碼器的輸出。
| 輸入 | Base64 | 填充 |
|---|---|---|
a | YQ== | == |
ab | YWI= | = |
abc | YWJj | — |
abcd | YWJjZA== | == |
hello | aGVsbG8= | = |
台北 | 5Y+w5YyX | — |
🎉 | 8J+OiQ== | == |
常見誤用
- 用 Base64 來「藏」資料:它一步就能還原,什麼都保護不了——請把它當信封,不是鎖。見 Base64 是加密嗎?
- 對整條網址做 URL 編碼:只該編碼各部分(查詢值、路徑片段),不是整個網址,否則
https://會變成https%3A%2F%2F,連結就壞了。 - 重複編碼:對已編碼的值再編一次會得到
%2520(連%本身都被轉義了)。若空格是以%2520而非%20抵達,就表示被編了兩次。 - 忘了 Base64 的
+與/:純 Base64 在網址裡並不安全;放進網址時請用 Base64URL,或把整串再做一次 URL 編碼。
Base64 最常見的誤用,是把它當成一種藏東西的方式,而這值得一個具體的值。admin:password 編碼是 YWRtaW46cGFzc3dvcmQ=,那正是 HTTP Basic 認證放進標頭的東西;而 {"role":"admin"} 編碼是 eyJyb2xlIjoiYWRtaW4ifQ==。兩個都不需要任何密鑰就解得開。百分號編碼從來不會被誤認成隱藏,因為它保持可讀;Base64 會被誤認,正是因為它不可讀。兩者都不是安全措施 —— 只是其中一個比較像。
各自出現在哪裡
- Base64 出現在任何要用文字承載二進位的地方:
data:URI、電子郵件的 MIME 區段、JWT 的各段,以及硬塞進 JSON 的二進位欄位。 - URL 編碼 出現在任何要把文字放進網址的地方:查詢字串、表單送出(
application/x-www-form-urlencoded),以及含空格或非 ASCII 字元的路徑片段。
常見問題
可以用 Base64 取代 URL 編碼嗎?
不行——兩者不能互換。Base64 讓二進位變成文字安全;URL 編碼讓文字變成網址安全。把純 Base64 直接放進網址,仍可能因為 +、/、= 而出錯。
為什麼我的 Base64 結尾是 =?
那是填補字元,用來把輸出長度補到 4 的倍數。這很正常,某些網址安全變體會省略它。
這兩種能讓資料變安全嗎?
不能。編碼講的是格式,不是保密——任何人都能還原。要保密得用加密;要防竄改得用雜湊或簽章。