两种编码,两个任务

Base64 和 URL 编码都会把「不安全」的字符替换成安全字符。这种表面相似,正是它们经常被搞混的原因——要么该用一种却用了两种,要么干脆用错了。

一句话版本:

  • Base64二进制数据能通过只支持文本的通道
  • 百分号编码文本能安全地放进 URL

各自到底做了什么

Base64 用 64 个字符的字母表(A–Z a–z 0–9 + /,末尾用 = 补齐)重写字节。每 3 个字节变成 4 个字符,体积因此增加约 33%。

Man     → TWFu
Hello   → SGVsbG8=

百分号编码把在 URL 里不安全的字符替换成 % 加两位十六进制数(对应 UTF-8 字节)。

a b            → a%20b
书签管理        → %E4%B9%A6%E7%AD%BE%E7%AE%A1%E7%90%86
a&b            → a%26b

关键区别

Base64 百分号编码
目的 让二进制穿过文本通道 让文本安全地待在 URL 里
字符集 固定的 64 个字符 任意字节,写成 %XX
体积变化 +33% 变化很大
谁能还原 任何人 任何人
提供安全性
常见位置 JSON 字段、data URI、邮件附件、JWT 查询参数、路径片段

什么时候用 Base64

  • 把小块图片以 data URI 内嵌进 CSS 或 HTML
  • JSON 里传文件、缩略图或签名
  • 通过 MIME 发邮件附件
  • 构造 Authorization: Basic 请求头
  • JWT 的 header 与 payload 段

需要双向转换时,直接用 Base64 编解码工具,不用装任何东西。

什么时候用百分号编码

  • 查询参数的值里含有 &=#?、空格或非 ASCII 字符
  • 文件名或 slug 要放进路径
  • 把一个 URL 当作另一个 URL 的参数传递(重复编码的 bug 就出在这里)

URL 编解码工具 用的是 encodeURIComponent,正是处理参数值时需要的行为。

三种最常见的坑

1. 该用百分号编码的地方用了 Base64。 Base64 里有 +/,直接放进查询串时,很多解析器会把 + 当成空格。解决办法:用 URL-safe 字母表(-_),或者对结果再做一次百分号编码。

2. 重复编码。 对已经编码过的内容再编码一次,会得到一层"看起来合法但毫无意义"的结果。典型特征是开头出现 %25%25 就是 %)。

3. 把两者当成加密。 两者都可以在没有任何密钥的情况下还原。需要保密就先加密,再编码。

我这种情况该用哪个?

只问一个问题:目标位置是 URL,还是文本容器?

  • URL(查询串、路径)→ 百分号编码
  • 文本容器(JSON、HTML 属性、邮件正文、CSS)→ 内容是二进制就用 Base64,否则保持纯文本

两个工具放一起试

常见问题

能先 Base64 再放进 URL 吗? 可以,但要先对 Base64 结果做百分号编码(或者直接用 Base64URL),否则 +/= 会出问题。

百分号编码一定比 Base64 长吗? 通常是。中文按 UTF-8 百分号编码后,一个汉字要 9 个字符,远超 Base64 的 33% 开销。

两者会压缩数据吗? 都不会。想减小体积先压缩(gzip / Brotli),再编码。

密码该用哪种? 都不用。用密码管理器加真正的加密——编码不等于保护。

相关阅读