前端AES加密后数据在传输时还是被拦截了怎么办?

夏沫 阅读 46

在表单提交时用AES加密了用户密码,但用抓包工具还是能看到明文数据,这正常吗?

我按网上的教程用了crypto-js写了个加密方法:


function encrypt(data) {
  return CryptoJS.AES.encrypt(data, 'my-secret-key', {
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  }).toString();
}

然后在表单提交前调用了这个函数,但用Postman抓包时发现请求体里的密码还是明文。难道前端加密没生效?

已经试过把密钥改成环境变量,换了不同的加密模式,甚至把加密函数写在立即执行函数里,但问题依旧存在。是不是加密逻辑哪里漏了?

我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
Top丶子涵
你这个问题其实挺常见的,很多同学一开始都会以为前端加密了就万事大吉,结果抓包一看还是明文,一脸懵。先说结论:你加密是加密了,但没加密对地方——你加密的是数据本身,但提交的时候可能又把原始数据提交上去了。

我猜你代码里大概长这样:

form.addEventListener('submit', (e) => {
e.preventDefault();
const password = document.querySelector('#password').value;
const encrypted = encrypt(password); // 这里加密了
// 但下面这行可能还是用的 password 而不是 encrypted!
fetch('/login', { method: 'POST', body: JSON.stringify({ password }) });
});


你加密了变量 encrypted,但提交的时候用的还是 password,那抓包当然看到明文啊。

我的做法是:确认提交时用的是加密后的字符串,比如:

fetch('/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password: encrypted })
});


另外再提醒两个容易踩的坑:

第一个是密钥问题。你写死在代码里的 'my-secret-key' 是明文,前端根本没法保密,别人打开 JS 文件就能看到。所以就算加密了,攻击者拿到密钥也能解密。前端加密主要防的是传输过程中的中间人偷窥,不是防客户端本身——它防不了浏览器里的代码被篡改。

第二个是,你用的是 CBC 模式,但没传 iv(初始化向量),crypto-js 默认会用一个固定的 iv(或者忽略),这会导致同样的明文每次加密结果一样,不安全。建议要么用默认的 OpenSSL 模式(不传 mode/padding),要么自己生成随机 iv 并拼在密文前面一起传:

function encrypt(data) {
const key = CryptoJS.enc.Utf8.parse('my-secret-key'); // 32字节才安全
const iv = CryptoJS.lib.WordArray.random(16); // 随机iv
const encrypted = CryptoJS.AES.encrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
// 把 iv 拼到密文前面,方便后端解密时提取
return iv.toString() + encrypted.toString();
}


最后说句实话:密码类敏感字段,前端加密只是锦上添花,真正靠谱的防护是后端必须走 HTTPS,再加个哈希存储(比如 bcrypt),别明文存数据库。前端加密防不住本地调试、JS 被注入这些情况。

你先检查下提交的字段是不是真的用了加密后的值,八成就是这儿的问题 😅
点赞 3
2026-02-24 14:07
宇文慧利
你这个情况一点都不奇怪,前端加密没生效是因为你根本没在提交前真正替换掉原始数据。

看你的代码,encrypt 函数写得没问题,但问题大概率出在表单处理逻辑上:你可能对密码做了加密,但最后发请求的时候还是把原始 input 的 value 塞进了 payload,而不是用 encrypt 后的结果。比如像这样:

const password = document.getElementById('password').value;
const encrypted = encrypt(password);
// 错误示范:还是传了原始 password
fetch('/login', {
method: 'POST',
body: JSON.stringify({ password }) // 啊!这里应该传 encrypted
});


你应该确保发送的是 encrypt(password) 的返回值,而且最好检查下网络请求的实际 payload,在 DevTools 的 Network 选项卡里看请求体,别用 Postman 模拟,直接看浏览器发出的原始数据才准。

不过更要命的是,就算你现在修好了加密,AES 前端硬编码密钥也防不住多少攻击。攻击者照样能反编译 JS 拿到密钥解密,中间人还是能看到“密文”转成明文的过程。真想防止注入和窃取,光靠前端加密是自欺欺人。

正确的做法是:前端加密只能作为纵深防御的一环,核心必须配合 HTTPS 防止传输层被嗅探,后端再做一次解密校验。密钥别写死在代码里,可以通过接口动态获取,加点时间戳或随机盐,防止重放。

还有,别忘了 XSS 风险,如果页面被注入脚本,你加密前的明文密码照样会被截走。所以 CSP 策略、输入过滤、HttpOnly cookie 这些基本防护一个都不能少。

总结:先修逻辑错误,确保加密后的数据真正被提交;然后别依赖前端加密当救命稻草,HTTPS + 安全的后端验证才是正道。
点赞 1
2026-02-11 22:01