前端接口加密怎么做才安全?
最近项目要求所有请求参数都要加密,但我试了在 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>
这样搞真的安全吗?密钥写死在前端是不是等于没加密?
另外,你使用的 ECB 模式也是不安全的。ECB 模式下相同的明文块会被加密成相同的密文块,容易被攻击者分析出模式。推荐使用 CBC 或 GCM 模式,并且每次加密都应该使用不同的初始化向量(IV)。
解决这个问题的方法通常是将加密逻辑移到后端,前端只负责发送数据,后端负责加密和解密。但是如果你确实需要在前端进行加密,可以考虑动态获取密钥的方式,比如通过安全的 HTTPS 请求从服务器获取一个一次性使用的密钥,然后使用这个密钥进行加密,加密完成后立即丢弃这个密钥,不再使用。
这里有一个改进的思路,虽然不是最优解,但比直接写死密钥好一些:
1. 在用户登录时,服务器生成一个临时密钥并返回给前端。
2. 前端使用这个临时密钥对数据进行加密。
3. 数据加密后,临时密钥不再保存在前端。
不过最安全的做法还是让后端处理加密和解密逻辑。下面是一个简化的示例,展示如何在后端生成密钥并传递给前端:
后端(Node.js + Express 示例):
前端(Vue 示例):
注意:这个示例只是一个基本的演示,实际应用中还需要考虑更多的安全细节,比如密钥的有效期、密钥的存储和销毁策略等。