如何将 Base64 转换为 Base64URL
- 把 Base64 粘贴到 输入 · Base64。换行 Base64 中的换行符和
data:...;base64,前缀会被自动去除。 - URL 安全的字符串显示在 输出 · Base64URL 中。
- 如果接收方要求保留末尾的
=,勾选输出下方的 填充(=)。 - 点击 复制输出。方向切换 Base64URL → Base64 或 Base64URL 转 Base64 可以转回去。
输入会先解码为字节再重新编码,所以无效的 Base64 字符串会直接报错,而不会得到一个转换了一半的结果。
示例
| Base64 | Base64URL | 说明 |
|---|---|---|
PDw/Pz8+Pg== | PDw_Pz8-Pg | 替换了 / 和 +,去掉了 == |
eyJyb2xlIjoiYWRtaW4+In0= | eyJyb2xlIjoiYWRtaW4-In0 | 含 > 的 JSON,去掉了一个 = |
E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw+cM= | E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM | RFC 7636 附录 B 中的 PKCE challenge |
+/8= | -_8 | 字节 fb ff |
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 | 没有变化:不含 +、/ 或 = |
最后一行的情况很常见。短 JSON 和 ASCII 文本编码后经常不含 + 或 /,长度是 3 字节的倍数时也没有填充,所以两种形式完全相同。这也是为什么忘记转换在测试中可能一直没被发现,直到某个值恰好产生了 + 或 /。
会破坏 URL 的标准 Base64 字符
标准 Base64 中有三个字符在 URL 里有特殊含义:
+在查询字符串中表示空格,所以?t=a+b在很多框架中收到的是a b。/用来分隔路径段,所以路径中的 Base64 可能被拆开或路由错误。=用来分隔查询参数的名和值,为了安全必须写成%3D。
RFC 4648 第 5 节为此定义了 Base64URL,用 - 和 _ 代替 + 和 /,填充则可以省略。这样的值放在路径、查询字符串、Cookie 或文件名中都无需转义。Base64 与 Base64URL 一文有详细介绍。
哪些场景必须使用 Base64URL
- JWT 和 JWS。 JSON Web Token 的三段都使用不带填充的 Base64URL。JWT 解码器 可以读取它们,JWT 中的 Base64 讲解了这种格式。
- OAuth PKCE。 哈希工具通常把 verifier 的 SHA-256 摘要输出为标准 Base64,而
code_challenge必须是这个摘要不带填充的 Base64URL。这一步转换就是最后一步。 - WebAuthn 和 JWK。 凭据 ID、challenge 以及 JSON Web Key 中的密钥参数都是 Base64URL。
- 签名 URL 和链接中的令牌,例如密码重置或下载链接,值位于路径或查询字符串中。
如果要把文本直接编码为 Base64URL,跳过中间的标准形式,请使用 Base64URL 编码器。
在代码中将 Base64 转为 Base64URL
import base64
base64.urlsafe_b64encode(b"<<???>>").rstrip(b"=").decode() # 'PDw_Pz8-Pg'
Buffer.from("PDw/Pz8+Pg==", "base64").toString("base64url"); // 'PDw_Pz8-Pg'
"PDw/Pz8+Pg==".replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, ""); // same, without Buffer
Python 的 urlsafe_b64encode 会保留填充,所以要加 rstrip。Node 的 "base64url" 编码会去掉填充。更多内容见 Python 和 Node.js 指南。
常见问题
转换成 Base64URL 会改变数据吗?
不会。两种字母表编码的是相同的字节,只有两个字符和填充不同。无论解码哪种形式,得到的字节都完全一样。
转换时要去掉 = 填充吗?
看接收方的要求。JWT(RFC 7515)和 PKCE(RFC 7636)要求不带填充。有些库两种都接受,少数老旧的解码器则必须带填充,这时请勾选 填充(=)。
能用正则表达式把 Base64 转成 Base64URL 吗?
可以。JavaScript 中用 s.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "")。它假定输入是干净的一行;如果来自 PEM 文件或邮件,请先去掉换行。
可以改为对标准 Base64 做百分号编码吗?
可以,但 +、/ 和 = 会变成 %2B、%2F 和 %3D,每个都占三个字符;而且在会把 URL 解码两次或把 + 当作空格的系统中,这个值仍然会出问题。Base64URL 没有这两个问题。