两种编码,两个任务
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 在线编解码 —— 支持文本与二进制,UTF-8 安全,可离线
- URL 在线编解码 —— 查询参数与路径
- Base64 编码是什么 —— 更详细的原理说明
- URL 编码完全指南 —— 百分号编码深入讲解
常见问题
能先 Base64 再放进 URL 吗?
可以,但要先对 Base64 结果做百分号编码(或者直接用 Base64URL),否则 +、/、= 会出问题。
百分号编码一定比 Base64 长吗? 通常是。中文按 UTF-8 百分号编码后,一个汉字要 9 个字符,远超 Base64 的 33% 开销。
两者会压缩数据吗? 都不会。想减小体积先压缩(gzip / Brotli),再编码。
密码该用哪种? 都不用。用密码管理器加真正的加密——编码不等于保护。