Fetch API 发送前需手动用 Web Crypto API 加密请求体,优先选用 AES-GCM 算法,密钥通过 PBKDF2 派生,每次加密生成新 IV 并连同 authTag 与密文一并发送,后端需完整接收四要素解密,建议封装 secureFetch 统一处理。

在 Fetch API 发送前对请求体加密,本质是先用 Web Crypto API 加密数据,再把密文作为 body 发送,而不是让 fetch 自动加密。浏览器不提供“自动加密上传”功能,必须手动完成加密、拼装、传输三步。
选对加密方式:优先用 AES-GCM
AES-GCM 是目前浏览器端最稳妥的选择,它同时提供机密性和完整性验证(带 authTag),避免被篡改。别用 AES-CBC,它没有认证机制,容易被攻击。
- 密钥不能写死,也不能从服务端直接下发明文密钥
- 推荐由用户输入密码 + 随机 salt + PBKDF2 派生密钥
- 每次加密都生成新 IV(12 字节推荐),IV 可公开,但必须随密文一起传给后端
分步处理请求体:读取 → 加密 → 构造 payload
不要一次性把大文件读进内存(比如 file.arrayBuffer() 处理几百 MB 文件会卡死)。对普通文本或中小 JSON 数据,可按以下流程:
- 把原始数据转成 ArrayBuffer(如 JSON 字符串用 encoder.encode(str).buffer)
- 调用 crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, data) 得到密文 ArrayBuffer
- 将 iv、authTag(需从加密结果中提取)、密文一起打包成对象,再 JSON.stringify 发送
示例片段:
立即学习“Java免费学习笔记(深入)”;
const encoder = new TextEncoder();
const dataBuf = encoder.encode(JSON.stringify({ user: 'alice', msg: 'hello' })).buffer;
const iv = crypto.getRandomValues(new Uint8Array(12));
const encrypted = await crypto.subtle.encrypt(
{ name: 'AES-GCM', iv },
key,
dataBuf
);
const result = {
iv: btoa(String.fromCharCode(...iv)),
ciphertext: btoa(String.fromCharCode(...new Uint8Array(encrypted))),
// authTag 需单独提取(encrypt 不返回,要用封装函数或 GCM 模式解析)
};
后端必须能解密:传全必要参数
前端加密后,后端解密缺一不可的要素有四个:
- 算法名(如 AES-GCM)
- IV(初始向量)
- 密文主体
- authTag(GCM 认证标签,长度通常 16 字节)
建议统一用 JSON 格式发送,字段命名清晰(如 iv、ciphertext、authTag),避免 base64 编码嵌套出错。Content-Type 仍设为 application/json,和普通接口保持一致。
封装加密 fetch 函数更安全可靠
重复写加密逻辑容易出错。建议封装一个 secureFetch,自动处理:
- 密钥派生(基于用户密码或已存密钥)
- IV 生成与附带
- 加密后构造标准 payload
- 透传其他 headers 和 method,不破坏原有 fetch 行为
这样业务层只需调用 secureFetch('/api/submit', { body: plainData }),无需关心加解密细节。


















