← 中文资源

简体中文版本

Base64URL 编解码工具

把字符串或字节编码为无填充 base64url,并以严格字符集、长度与 UTF-8 校验解码。

阅读英文原文

功能说明

该示例实现 base64url 的编码与解码。base64url 把标准 Base64 中的加号与斜杠替换为连字符与下划线,并去掉末尾填充,因此可以安全地放进 URL、Cookie 和 JWT 片段。编码支持字符串与 Uint8Array,解码默认按 UTF-8 严格模式还原文本。

关键代码

encodeBase64Url 先把输入统一为字节,再逐字节拼成二进制字符串交给 btoa,最后替换字符并去掉等号。decodeBase64Url 先校验字符集与长度,长度除以 4 余 1 一定是非法输入;随后补回等号、还原字符集并用 atob 得到二进制串,再通过 Uint8Array.from 与 TextDecoder 解码。TextDecoder 的 fatal 选项会把非法 UTF-8 直接抛错,而不是悄悄替换成问号。

使用注意

btoa 与 atob 在浏览器和较新的 Node 中都可用,但如果运行环境缺失需要自行提供实现。编码二进制数据后解码为文本可能得到乱码,应改为返回字节数组。base64url 不是加密,也不能防篡改,JWT 的完整性必须依赖签名校验。解码前仍应限制输入长度,避免超大字符串占用内存。

验证方式

对 user:42 编码得到 dXNlcjo0Mg,再解码断言还原原文。测试中文与表情符号的往返,确认 UTF-8 未被破坏。传入包含加号、斜杠或空格的字符串断言抛错,长度为 1 的输入也抛错。最后用非法 UTF-8 字节序列断言解码抛错。

代码示例

export function encodeBase64Url(input) {
  const bytes = toBytes(input);
  let binary = "";
  for (const byte of bytes) binary += String.fromCharCode(byte);
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

export function decodeBase64Url(input, options = {}) {
  if (typeof input !== "string") throw new TypeError("input must be a string");
  if (!/^[A-Za-z0-9_-]*$/.test(input)) throw new Error("input contains invalid base64url characters");
  if (input.length % 4 === 1) throw new Error("input has an invalid base64url length");
  const { encoding = "utf-8" } = options;
  const padded =
    input.replace(/-/g, "+").replace(/_/g, "/") + "=".repeat((4 - (input.length % 4)) % 4);
  const binary = atob(padded);
  const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
  return new TextDecoder(encoding, { fatal: true }).decode(bytes);
}

function toBytes(input) {
  if (typeof input === "string") return new TextEncoder().encode(input);
  if (input instanceof Uint8Array) return input;
  throw new TypeError("input must be a string or Uint8Array");
}

const token = encodeBase64Url("user:42");
console.log(token);
console.log(decodeBase64Url(token));
console.log(encodeBase64Url(new Uint8Array([251, 255, 190])));