第 6 课

常见 Base64 错误

字母表混用、换行符、UTF-8 文本解码错误等。

Base64 相关的坑,大多集中在四类:字母表/变体不一致空白与换行重复编码,以及把 UTF-8 文本原始字节 混为一谈。

字母表“乱炖”

典型现象:

  • 一会儿用标准 Base64(+//),一会儿用 URL-safe(-/_),随机失败;
  • 从某处复制来的“像 JWT 的片段”里仍带着 +/,但服务端按 Base64URL 解析。

治理方式:在代码里 集中封装 编解码路径;为 MIME(有填充)Base64URL(常无填充) 各准备一组 黄金样例 做往返测试。

不要在多个服务里散落正则“随手替换”——迟早有一条路径忘了 trim 或规范化顺序不对。

大小写敏感

A–Za–z 在索引表中有不同含义。若对整段载荷误用 .toLowerCase() / .toUpperCase(),会在信息层面 破坏数据

空白与换行残留

从 PDF、邮件、聊天里复制,常会夹进 软换行行首行尾空格,甚至 不可见 Unicode 空白(如窄不间断空格、BOM)。

策略:

  • 仅在 规范明确允许 时,才使用库提供的“忽略空白”选项;
  • PEM 会剥掉头尾 -----BEGIN... 行,但 不保证自动处理正文里所有奇怪空格;
  • 日志切分可能把一条 Base64 截成多行——对异常短的片段要 拒绝或告警

更稳妥的是:在入口做 显式白名单式规范化(允许哪些字符、如何处理换行),而不是依赖“宽松解码”碰运气。

URL 解码顺序

对查询串先 decodeURIComponent 两次、或和 Base64 规范化 顺序搞反,很容易得到乱码字节——尤其要留意 %2B%2F%3D(对应 +/=)。

在网关/代理链路里,尽量在框架改写参数 之前拿到原始 query 做诊断。

不小心“套娃”编码

有人把 JSON 先 Base64 一次,拿到字符串后又 再 Base64 一次 存库——最终产物和任何一方的假设都对不上。

在代码与文档里写清 每一层编码的职责(必要时用显式函数名,如 encodeLayer1),并在日志里对敏感值只打印 长度 + 指纹摘要,避免泄露明文。

UTF-8 文本与字节的混淆

“我的中文串被你 Base64 坏了。”常见根因是:

  • 字符串对象UTF-8 字节序列 的边界理解不清;
  • 误用默认代码页(历史上 Windows 区域设置导致 乱码);
  • 与服务端 JSON 序列化 是否带 BOM、是否 pretty-print 不一致导致字节不同。

正确心智:

Unicode 字符串 →(按约定,多为 UTF-8)→ 字节 → Base64 → ASCII 文本

每一跳都要明确:这一跳处理的是文本还是 opaque bytes

JSON 载荷

JSON 在互操作里通常以 UTF-8 字节为准。应对 完整 JSON 文档的字节做 Base64,而不是对“看起来一样”的两种格式化结果想当然。

数据库里的类型

把 Base64 解码后的 protobuf 误存进带排序规则(collation)的 TEXT 列,理论上不该做,但 ORM 误标类型时真的见过 悄悄损坏——能标 BYTEA/BLOB 就别走文本捷径。

安全相关提醒

Base64 不是保密。在不可信链路上只“Base64 一下”等于 明文

涉及签名 / MAC 时,规范字节布局(包括填充形式、是否 URL-safe)变了,验证会 无声失败——要对 规范级测试向量 做回归。

若比较的是高敏感令牌,避免手写字符串 == 引入时间侧信道——用密码库提供的 常量时间比较(问题不来自 Base64 本身,但常与令牌管道相邻)。

要点小结

团队若要稳,至少对齐这四件事:

  1. 使用哪套字母表与填充规则(MIME / Base64URL / 其它)
  2. 解码前的规范化顺序(URL 步骤、去折行策略)
  3. 内容到底是 UTF-8 文本 还是 不透明字节
  4. 禁止无文档的 层层套娃编码

黄金向量 放进 CI,能在早期抓住回归,而不是靠线上用户帮你试出来。

想动手练习时,可使用 DevCove 相关工具——可选,不属于本课正文。

打开相关工具

返回课程概览