前端接口加密怎么做才安全?

祖溢(打工版) 阅读 4

最近项目要求所有请求参数都要加密,但我试了在 Vue 里用 AES 加密后发给后端,结果后端解密总是失败,不知道是不是我加密方式有问题。

我用的是 CryptoJS,加密逻辑写在 axios 请求拦截器里,但不确定密钥怎么管理才安全。现在代码大概长这样:

<script setup>
import axios from 'axios'
import CryptoJS from 'crypto-js'

const encryptData = (data) => {
  const key = CryptoJS.enc.Utf8.parse('1234567890abcdef') // 临时密钥
  const encrypted = CryptoJS.AES.encrypt(JSON.stringify(data), key, {
    mode: CryptoJS.mode.ECB,
    padding: CryptoJS.pad.Pkcs7
  })
  return encrypted.toString()
}

axios.interceptors.request.use(config => {
  if (config.data) config.data = { data: encryptData(config.data) }
  return config
})
</script>

这样搞真的安全吗?密钥写死在前端是不是等于没加密?

我来解答 赞 2 收藏
二维码
手机扫码查看
1 条解答
上官璐莹
按照规范来说,前端直接写死密钥确实是非常不安全的做法。密钥应该只存在于服务器端,并且不应该在网络传输中暴露。你当前的实现中,密钥硬编码在前端代码里,任何人都可以通过查看源码获取到这个密钥,这等于没有加密。

另外,你使用的 ECB 模式也是不安全的。ECB 模式下相同的明文块会被加密成相同的密文块,容易被攻击者分析出模式。推荐使用 CBC 或 GCM 模式,并且每次加密都应该使用不同的初始化向量(IV)。

解决这个问题的方法通常是将加密逻辑移到后端,前端只负责发送数据,后端负责加密和解密。但是如果你确实需要在前端进行加密,可以考虑动态获取密钥的方式,比如通过安全的 HTTPS 请求从服务器获取一个一次性使用的密钥,然后使用这个密钥进行加密,加密完成后立即丢弃这个密钥,不再使用。

这里有一个改进的思路,虽然不是最优解,但比直接写死密钥好一些:

1. 在用户登录时,服务器生成一个临时密钥并返回给前端。
2. 前端使用这个临时密钥对数据进行加密。
3. 数据加密后,临时密钥不再保存在前端。

不过最安全的做法还是让后端处理加密和解密逻辑。下面是一个简化的示例,展示如何在后端生成密钥并传递给前端:

后端(Node.js + Express 示例):
const express = require('express');
const crypto = require('crypto');
const app = express();

app.use(express.json());

app.post('/get-key', (req, res) => {
const key = crypto.randomBytes(16).toString('hex'); // 生成一个随机的16字节密钥
res.json({ key });
});

app.post('/submit-data', (req, res) => {
// 这里应该是解密逻辑
res.send('Data received and decrypted successfully.');
});

app.listen(3000, () => {
console.log('Server is running on port 3000');
});


前端(Vue 示例):
<script setup>
import axios from 'axios';
import CryptoJS from 'crypto-js';

let tempKey = '';

const fetchTempKey = async () => {
const response = await axios.post('http://localhost:3000/get-key');
tempKey = response.data.key;
};

const encryptData = (data) => {
const key = CryptoJS.enc.Utf8.parse(tempKey);
const iv = CryptoJS.lib.WordArray.random(16); // 生成一个随机的16字节IV
const encrypted = CryptoJS.AES.encrypt(JSON.stringify(data), key, {
iv: iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
return { encrypted: encrypted.toString(), iv: iv.toString() };
};

axios.interceptors.request.use(async config => {
if (config.url === '/submit-data') {
await fetchTempKey();
config.data = encryptData(config.data);
}
return config;
});

// 提交数据的示例
const submitData = async () => {
const data = { message: 'Hello, world!' };
try {
const response = await axios.post('http://localhost:3000/submit-data', data);
console.log(response.data);
} catch (error) {
console.error(error);
}
};
</script>


注意:这个示例只是一个基本的演示,实际应用中还需要考虑更多的安全细节,比如密钥的有效期、密钥的存储和销毁策略等。
点赞
2026-03-22 19:06