一种编码,两个字母表

Base64 将任意字节转换为 64 个可打印字符,每三个输入字节对应四个输出字符。标准字母表(RFC 4648 第 4 节)是 AZaz09 以及两个符号 +/,并用 = 来填充最后一组。

问题在于 +/= 在其他场合具有特殊含义。在 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 安全字母表进行编码和解码,处理缺失的填充并显示原始字节,全部在你的浏览器中完成。你粘贴的任何内容都不会被发送到任何地方。