首页 / 专栏 / njs / NJS 中的 Base64 编解码:atob() 与 btoa() 全解析

NJS 中的 Base64 编解码:atob() 与 btoa() 全解析

  • 发布时间: 2026-01-10 22:45:21
  • 相关标签: NJS Base64 atob btoa
  • 简介: Base64 是一种通用的二进制到文本的编码方式,常用于处理特殊字符传输、加密数据序列化等场景。NJS(NGINX JavaScript)内置了 Web 标准的 `atob()` 和 `btoa()` 方法,无需依赖第三方模块即可实现高效的 Base64 编解码,是 NGINX 网关层处理数据编码的轻量解决方案。本文将详细讲解这两个方法的用法、适用场景及注意事项,结合实战示例展示其在 NJS 中的典型应用。

手机扫码查看

一、atob()/btoa() 核心定位

atob()btoa() 是 NJS 实现 Base64 编解码的原生方法,完全兼容 Web API 标准,核心作用:

  • btoa():将二进制字符串编码为 Base64 格式的 ASCII 字符串,解决特殊字符(如 ASCII 0-31 控制字符)传输时的兼容性问题;
  • atob():将 Base64 编码的字符串解码为原始二进制字符串,还原编码前的数据。

核心特点:轻量无依赖、执行效率高,仅处理字符串类型数据,是 NGINX 网关层(如请求参数解码、响应数据编码)的首选方案。

二、核心方法详解

2.1 btoa():Base64 编码

语法

btoa(stringToEncode)
参数 类型 说明
stringToEncode 二进制字符串 待编码的原始字符串(可包含 ASCII 0-31 控制字符)
返回值 ASCII 字符串 Base64 编码后的结果,仅包含 Base64 字符集(A-Z、a-z、0-9、+、/、=)

基础示例

// 普通字符串编码
const rawStr = "text to encode";
const encodedStr = btoa(rawStr);
console.log(encodedStr); // 输出:dGV4dCB0byBlbmNvZGU=

// 包含控制字符的字符串编码(ASCII 0 为 null 字符)
const controlStr = "hello" + String.fromCharCode(0) + "world";
const encodedControlStr = btoa(controlStr);
console.log(encodedControlStr); // 输出:aGVsbG8Ad29ybGQ=

2.2 atob():Base64 解码

语法

atob(encodedData)
参数 类型 说明
encodedData ASCII 字符串 Base64 编码后的字符串
返回值 二进制字符串 解码后的原始字符串,还原编码前的所有字符(包括控制字符)

基础示例

// 解码普通字符串
const encodedStr = "dGV4dCB0byBlbmNvZGU=";
const decodedStr = atob(encodedStr);
console.log(decodedStr); // 输出:text to encode

// 解码包含控制字符的字符串
const encodedControlStr = "aGVsbG8Ad29ybGQ=";
const decodedControlStr = atob(encodedControlStr);
console.log(decodedControlStr); // 输出:hello\u0000world(\u0000 为 ASCII 0 字符)

2.3 编解码完整流程

// 封装编解码工具函数
function base64Encode(r, rawData) {
    try {
        return btoa(rawData);
    } catch (e) {
        r.error(`Base64 编码失败:${e.message}`);
        return null;
    }
}

function base64Decode(r, encodedData) {
    try {
        return atob(encodedData);
    } catch (e) {
        r.error(`Base64 解码失败:${e.message}`);
        return null;
    }
}

// 使用示例
function handleEncodeDecode(r) {
    const raw = "NGINX NJS Base64 Demo";
    const encoded = base64Encode(r, raw);
    const decoded = base64Decode(r, encoded);
    
    r.log(`原始数据:${raw}`);
    r.log(`编码后:${encoded}`); // TkdJTlggTkpTIEJhc2U2NCBEZW1v
    r.log(`解码后:${decoded}`); // NGINX NJS Base64 Demo
    
    r.return(200, `编码结果:${encoded}\n解码结果:${decoded}`);
}

三、实战场景:NJS 网关层的编解码应用

3.1 场景1:解码请求头中的 Base64 认证信息

HTTP Basic 认证的 Authorization 头格式为 Basic <Base64编码的用户名:密码>,可通过 atob() 解码获取原始凭证:

# NGINX 配置
http {
    js_import auth.js;
    server {
        listen 80;
        location /api {
            js_access auth.verifyBasicAuth; # 访问前校验认证
            proxy_pass http://backend;
        }
    }
}
// auth.js
function verifyBasicAuth(r) {
    // 获取 Authorization 头
    const authHeader = r.headersIn.Authorization;
    if (!authHeader || !authHeader.startsWith("Basic ")) {
        r.return(401, "未授权:缺少 Basic 认证信息");
        return;
    }
    
    // 提取 Base64 编码部分并解码
    const encodedCreds = authHeader.slice(6); // 去掉 "Basic " 前缀
    const decodedCreds = atob(encodedCreds);
    const [username, password] = decodedCreds.split(":");
    
    // 校验凭证(实际场景应从配置/数据库获取)
    const validUser = "admin";
    const validPwd = "123456";
    
    if (username === validUser && password === validPwd) {
        r.log(`用户 ${username} 认证通过`);
        r.next(); // 放行请求
    } else {
        r.warn(`用户 ${username} 认证失败`);
        r.return(401, "认证失败:用户名或密码错误");
    }
}

export default { verifyBasicAuth };

3.2 场景2:编码响应数据中的特殊字符

当响应包含不可打印字符(如 ASCII 控制字符、特殊符号)时,通过 btoa() 编码后传输,客户端再解码:

# NGINX 配置
http {
    js_import encode.js;
    server {
        listen 80;
        location /data {
            js_content encode.specialCharEncode;
        }
    }
}
// encode.js
function specialCharEncode(r) {
    // 模拟包含控制字符和特殊符号的原始数据
    const rawData = {
        id: 1001,
        content: "核心数据\u0007\u0010", // \u0007(响铃)、\u0010(数据链路转义)
        timestamp: new Date().toISOString()
    };
    
    // 序列化并编码
    const jsonStr = JSON.stringify(rawData);
    const encodedData = btoa(jsonStr);
    
    // 设置响应头,告知客户端需解码
    r.headersOut['Content-Type'] = 'text/plain';
    r.headersOut['X-Data-Encoding'] = 'base64';
    
    // 返回编码后的数据
    r.return(200, encodedData);
}

export default { specialCharEncode };

3.3 场景3:编解码 URL 参数中的特殊字符

URL 参数不支持部分特殊字符(如 /+=),可通过 Base64 编码避免参数解析错误:

// 处理 URL 参数编解码
function handleParamEncode(r) {
    // 读取客户端传入的 Base64 编码参数
    const encodedParam = r.args.data || "";
    if (!encodedParam) {
        r.return(400, "缺少 data 参数(Base64 编码)");
        return;
    }
    
    // 解码参数
    const decodedParam = atob(encodedParam);
    r.log(`解码后的参数:${decodedParam}`);
    
    // 处理参数(示例:提取包含特殊字符的路径)
    const path = decodedParam;
    r.internalRedirect(path); // 内部重定向到解码后的路径
}

四、注意事项与常见问题

4.1 字符编码限制

  • btoa() 仅支持 二进制字符串(即每个字符的 Unicode 码点 ≤ 255),若传入包含多字节 Unicode 字符(如中文、emoji)的字符串,会抛出错误:
    // 错误示例:包含中文(Unicode 码点 > 255)
    btoa("中文"); // 抛出 DOMException: The string to be encoded contains characters outside of the Latin1 range.
    
  • 解决方法:先将多字节字符串转换为 UTF-8 二进制字符串,再编码(NJS 可通过 Buffer 辅助转换):
    // 兼容多字节字符的编解码
    function utf8ToBase64(str) {
        // 将字符串转换为 UTF-8 Buffer,再转为二进制字符串
        const buffer = Buffer.from(str, 'utf8');
        const binaryStr = String.fromCharCode(...new Uint8Array(buffer));
        return btoa(binaryStr);
    }
    
    function base64ToUtf8(encoded) {
        const binaryStr = atob(encoded);
        const buffer = new Uint8Array(binaryStr.split('').map(c => c.charCodeAt(0)));
        return Buffer.from(buffer).toString('utf8');
    }
    
    // 使用示例
    const chineseStr = "NJS 中文测试";
    const encoded = utf8ToBase64(chineseStr); // TkpTIOi2veWbveS6rOmDveivlQ==
    const decoded = base64ToUtf8(encoded); // NJS 中文测试
    

4.2 错误处理

  • 传入无效 Base64 字符串(如包含非 Base64 字符、长度不是 4 的倍数)时,atob() 会抛出异常;
  • 编码空字符串时,btoa() 返回空字符串,不会报错;
  • 建议始终用 try/catch 包裹编解码逻辑,避免脚本崩溃。

4.3 性能考量

  • atob()/btoa() 是原生方法,执行效率远高于自定义 Base64 实现;
  • 避免对超大字符串(如 MB 级)频繁编解码,建议在后端处理,NJS 仅处理轻量级数据(如认证信息、短参数)。

五、总结

  1. NJS 内置的 atob()/btoa() 是轻量高效的 Base64 编解码工具,兼容 Web API 标准,无需依赖第三方模块;
  2. btoa() 用于将二进制字符串编码为 Base64 ASCII 字符串,atob() 用于反向解码,核心解决特殊字符传输问题;
  3. 典型应用场景包括认证头解码、特殊字符参数处理、响应数据编码,需注意多字节字符(如中文)的兼容处理;
  4. 使用时需通过 try/catch 捕获异常,避免无效编码/解码导致请求处理失败。

同分类推荐