一种编码,两个字母表
Base64 将任意字节转换为 64 个可打印字符,每三个输入字节对应四个输出字符。标准字母表(RFC 4648 第 4 节)是 A 到 Z、a 到 z、0 到 9 以及两个符号 + 和 /,并用 = 来填充最后一组。
问题在于 +、/ 和 = 在其他场合具有特殊含义。在 URL 中,/ 是路径分隔符,+ 在查询字符串中历史上表示空格,而 = 用来分隔键和值。在文件名中,/ 在大多数系统上是非法的。因此原始 Base64 无法放入 URL 或文件名而不被破坏或需要额外的转义。
Base64URL 改变了什么
Base64URL(RFC 4648 第 5 节)是采用更安全字母表的同一种编码。恰好有两个字符不同:
+变为-(连字符)/变为_(下划线)
其余所有字符都相同,三字节到四字符的算法也不变。结果是一个字符串,能在 URL 路径、查询参数或文件名中安然存放,无需任何百分号编码。
填充是另一个区别。标准 Base64 用 = 把最后一组补足到四的倍数。Base64URL 通常完全省略填充,因为 = 在 URL 中同样麻烦。解码器始终可以根据字符串的长度重新算出去掉了多少填充,因此不会丢失任何内容。
它真正出现在哪里
Base64URL 并非规范中的冷僻角落。它是你经常使用的若干东西背后的编码:
- JSON Web Token。 一个 由三段以点连接的 Base64URL 组成(
header.payload.signature)。+//的替换以及省略的=,正是令令牌成为一个干净、URL 安全字符串的原因。 - 。 授权码流程中的
code_challenge是一个 哈希的 Base64URL 编码(无填充),正是为了让它能在 URL 中传递。 - Web Push、 和许多令牌 都以同样的方式编码其二进制字段。
一条实用提醒
由于字母表高度重叠,一个 Base64URL 字符串与一个标准 Base64 字符串可能看起来几乎相同,而一个不含 +、/ 或 = 的值在两者中都有效。只有当原始字节产生 -/_ 或 +// 时不兼容才会显现,此时用错误的字母表解码会失败或产生乱码。当一个令牌无法解码时,字母表是首先要检查的。
Base64 工具 可对标准字母表和 URL 安全字母表进行编码和解码,处理缺失的填充并显示原始字节,全部在你的浏览器中完成。你粘贴的任何内容都不会被发送到任何地方。