Java 做 Base64 Url Encode
Contents
之前我在有關 url 空白字符(%20和+) | 程式狂想筆記有記過,URL 中的 + 很容易被當成空白處理。所以如果把一般 Base64 字串直接塞進 query string,就很有機會踩雷。
為什麼一般 Base64 不適合直接放 URL
標準 Base64 常見字元包含:
+/=
這幾個字元放在 URL、路由參數、表單傳送時,都可能需要額外處理。尤其 + 在某些情境下會被解讀成空白,最後 server 端拿到的字串就跟原本不一樣了。
例如下面這個請求:
https://httpbin.org/get?test=123+123
如果你原本以為 + 會原封不動傳過去,很容易就會被這種結果陰到。
解法:使用 URL Safe Base64
所謂 URL Safe Base64,核心就是把不適合出現在 URL 的字元換成較安全的版本。常見規則是:
+改成-/改成_- 視情況去掉尾端
=padding
這樣就更適合放在 query string、JWT 片段、下載 token 或短網址參數。
Java 內建寫法
如果是 Java 8 之後,其實可以先用 JDK 內建的 Base64:
|
|
這種寫法的好處是少一個相依套件,而且語意很直接。
Apache Commons 寫法
如果專案本來就有用 Apache Commons Codec,也可以直接用:
|
|
這也是我當時查到後先記下來的方式。對應程式碼可以參考:
它有個不錯的地方是,URL Safe encode 出來的字串,仍然可以用 decodeBase64 做還原。
什麼時候特別需要注意
下面幾種場景,我會直接優先用 URL Safe Base64:
- 資料要放在 GET 參數。
- 資料要放在網址 path segment。
- 前後端之間會手動拼接 URL。
- token 會出現在瀏覽器網址列。
如果你的資料只是存在資料庫、寫檔案、放 JSON body,其實就不一定非要用 URL Safe 版本。
小結
這個問題本質上不是 Base64 壞掉,而是標準 Base64 的字元集合不一定適合拿來當 URL 參數。只要知道這點,以後看到網址中的 +、/、=,就會自然警覺是不是該改用 URL Safe 版本。