React发送POST请求时AES加密参数总是报错怎么办?
最近在做一个用户登录页面,需要对接后端提供的AES加密接口。按照文档要求,我得在发送请求前把手机号和密码用AES-128-ECB加密,但测试时后端一直返回”解密失败”的错误…
我的React代码是这样的(用的是crypto-js库):
import CryptoJS from 'crypto-js';
const handleSubmit = async (formData) => {
const encrypted = CryptoJS.AES.encrypt(
formData.phone + ':' + formData.password,
CryptoJS.enc.Utf8.parse('1234567812345678'), // 16位密钥
{ mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }
).toString();
try {
const res = await fetch('/api/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ encryptedData: encrypted })
});
// ...后续处理
} catch (err) {
console.error('加密请求失败:', err);
}
};
我检查过密钥长度是16位没问题,也确认了服务端用Java的AES-ECB-PKCS5Padding处理。但每次后端都说”BadPadding”错误,搞不懂是加密方式不对还是数据格式有问题?有没有做过类似加密的同学帮忙看看?
更关键的是:你传了密钥解析方式有问题。CryptoJS.AES.encrypt 的第二个参数应该是密钥字符串,而不是通过 CryptoJS.enc.Utf8.parse 预处理过的对象。虽然它能运行,但这容易导致两边加解密不一致。
还有,ECB 模式在前后端跨语言使用时特别敏感,Java 常用的是基于原始字节的处理,而 JS 的字符串编码、数据类型稍有偏差就会出错。
试试改成这样:
然后让后端同事确认他们是不是期望接收十六进制字符串。如果是接收 base64,你可以改用
encrypted.ciphertext.toString(CryptoJS.enc.Base64),但必须和后端约定好编码方式。另外提醒一句,前端做 AES 其实意义不大,密钥都暴露在客户端了,建议你们后端评估下安全性设计是否合理。现在这问题大概率就是编码格式对不上,尤其是 hex 和 base64 混用了。
先说解决方案:试试这个方法,把加密结果转成Base64,并且明确指定输出格式
重点是你原来用了
.toString(),这会包含多余的元信息(比如salt),而后端只想要密文部分。现在改成encrypted.ciphertext.toString(CryptoJS.enc.Base64)就只传真正的密文数据。另外确认下你们后端是不是真用PKCS5Padding?虽然你说是PKCS5,但AES-128一般用Pkcs7,Java里这两个在16字节块下其实是一样的,不会导致错误,不过最好让后端同事确认下他们的Cipher.getInstance("AES/ECB/PKCS5Padding")配置有没有问题。
如果还报错,让你那后端兄弟打个日志看看收到的Base64能不能正常decode成byte[],有时候前端发过去的字符串多了空格或换行也会炸。