前端请求响应加密怎么做才安全?

UI淑然 阅读 3

我最近在做登录接口,后端要求所有请求和响应都要加密,但我试了 AES 加密后发现密钥放前端根本藏不住,这不等于白加密吗?

我看到有些项目用 HTTPS 就行了,但后端坚持要应用层再加密一层。有没有既安全又可行的方案?总不能让用户自己输密钥吧……

顺便贴一下我测试时写的样式,虽然和加密无关,但怕影响整体结构:

.secure-form {
  padding: 16px;
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  background: #f9f9f9;
}
.secure-form input {
  width: 100%;
  padding: 8px;
  margin: 4px 0;
}
我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
Code°梓轩
你这个问题很常见,很多人都会踩坑。直接说结论:在已经有 HTTPS 的情况下,应用层再加密一层其实意义有限,但如果你后端非要这么做,可以用动态密钥的方案。

核心问题就是你说的,密钥放前端怎么都藏不住,再怎么混淆都能被扣出来。

解决方案其实不复杂:用后端的公钥加密一个随机生成的对称密钥,每次请求时动态生成。流程是这样的:

1. 后端生成一对 RSA 公钥私钥,公钥直接丢前端(这个泄露了没事)
2. 每次用户登录或每次请求前,前端用 Web Crypto API 生成一个随机 AES 密钥
3. 用后端的公钥把这个 AES 密钥加密,发送给后端
4. 后端用私钥解密,得到 AES 密钥,然后用这个密钥加密响应返回给前端
5. 前端用同样的 AES 密钥解密

这样每次通信用的都是不同的临时密钥,即使前端代码被逆向,也只能拿到公钥,拿不到实际的会话密钥。

简单实现的话大概这样:

// 生成随机 AES 密钥
async function generateAesKey() {
return await window.crypto.subtle.generateKey(
{ name: 'AES-GCM', length: 256 },
true,
['encrypt', 'decrypt']
);
}

// 用公钥加密 AES 密钥(需要把公钥导入为 CryptoKey)
async function encryptKeyWithPublicKey(aesKey, publicKeyJson) {
const publicKey = await window.crypto.subtle.importKey(
'jwk',
publicKeyJson,
{ name: 'RSA-OAEP', hash: 'SHA-256' },
false,
['encrypt']
);

const exportedKey = await window.crypto.subtle.exportKey('raw', aesKey);
const encryptedKey = await window.crypto.subtle.encrypt(
{ name: 'RSA-OAEP' },
publicKey,
exportedKey
);

return Array.from(new Uint8Array(encryptedKey));
}


响应加密解密用 AES-GCM 模式,记得每次通信都要生成新的 IV。

不过说句实在话的,如果你们后端的安全需求不是特别变态(防内部人员那种),真没必要在应用层再套一层。HTTPS + 证书固定就已经够用了。应用层加密会增加前端计算负担,用户体验也会受影响,你们后端要是能沟通的话,建议再聊聊。
点赞
2026-03-17 19:01