前端加解密实践:从「别明文传密码」开始
目录
每次提到前端加密,评论区都会有人说:
有 HTTPS 了,还加什么密?
前端代码都是能看到的,没意义。
理论上没错,但在金融/政企等场景里,有些需求不是技术可不可行,而是「要不要多一层安全防护 + 满足合规要求」。
这篇文章从实战出发,聊聊:
- 常见的前端加密需求;
- 对称 / 非对称加密如何组合使用;
- 以及实际落地时的一些坑。
1. HTTPS 已经有了,为啥还要前端加密?
先说前提:HTTPS 必须有,这是基础。
在这个基础上,某些场景仍然会要求:
-
防止明文敏感信息出现在抓包里
- 即便是 HTTPS,有些合规要求会明确写「不得以明文形式传输密码等敏感信息」;
- 抓包截图里看到一串密文,和直接看到手机号/密码,感受是不一样的。
-
降低中间层日志泄露风险
- 有时候请求会经过网关、代理、日志系统;
- 如果这些地方有不规范的日志记录,敏感字段加密可以降低损害。
-
和现有后端架构/第三方接口对齐
- 有些历史系统已经约定「密码字段用某种算法加密再传」;
- 前端需要遵守既有协议。
前端加密不是代替 HTTPS,而是多一层「应用层加密」。
2. 两个基本工具:对称 & 非对称
简单回顾一下:
- 对称加密(如 AES、SM4):同一把 key 加密解密;
- 非对称加密(如 RSA):公钥加密,私钥解密(或反之)。
特性:
- 对称加密:速度快,适合加密大量数据,但key 如何安全分发是问题;
- 非对称加密:适合做「密钥交换」,但加密大数据性能较差。
所以常用组合是:
前端生成一个随机对称密钥 → 用后端公钥加密这个密钥 → 发给后端 → 后端用私钥解出密钥 → 后续用这个对称密钥加解密数据。
前端常见实现方式:
- WebCrypto API;
- 或成熟的 JS 加密库(CryptoJS / JSEncrypt / 国密相关库等)。
3. 一个典型的前端加密流程
以「登录密码不可明文传输」为例,设计一个简化流程:
3.1 拉取公钥
在进入登录页或打开系统时:
const resp = await api.getEncryptConfig();
// resp.publicKey / resp.keyId
接口返回:
{
"keyId": "20220526",
"publicKey": "-----BEGIN PUBLIC KEY-----...",
"algorithm": "RSA"
}
前端缓存 publicKey 和 keyId。
3.2 构造待加密数据
用户提交表单时,把密码打包:
const payload = JSON.stringify({
password: plainPassword,
timestamp: Date.now(),
});
3.3 使用公钥加密
借助加密库,例如:
import JSEncrypt from 'jsencrypt';
const encryptor = new JSEncrypt();
encryptor.setPublicKey(publicKey);
const cipher = encryptor.encrypt(payload);
3.4 携带 keyId 与密文
请求参数变为:
{
"username": "test-user",
"password": "Base64EncodedCipher",
"keyId": "20220526"
}
后端据此:
- 通过
keyId找到对应私钥; - 解密出原始
payload; - 再继续后续登录逻辑。
更高级一点的做法是上面提到的「前端用公钥加密对称密钥,再用对称密钥加密密码」,这里就不展开。
4. 实战中的几个常见坑
4.1 字符编码和长度
非对称加密(比如 RSA)对加密数据长度有限制:
- 与 key 长度、填充方式有关;
- 明文过长会导致加密失败。
解决方式:
- 密码这种短字符串直接 RSA 问题不大;
- 大字段(如 JSON 整包)用对称加密,再用 RSA 保护对称密钥。
同时注意:
- 使用统一的编码(UTF-8);
- 加密后用 Base64 进行传输。
4.2 性能问题
- 加密/解密是 CPU 密集型操作;
- 手机低端机上做多次 RSA 运算会有明显卡顿。
经验:
- 只加密真正敏感的小字段(密码、交易 PIN 等);
- 不要整页所有字段都做复杂加密;
- 可以在「点击提交」时再进行加密,避免输入过程中阻塞。
4.3 密钥轮换
- 公钥/私钥不可能永久不变;
- 需要支持「新老 key 并存一段时间」。
前端配合方式:
- 每次从服务端获取最新加密配置(可能包含多个 key);
- 请求里带上
keyId,后端据此选用对应私钥解密; - 一段时间后下线老 key。
4.4 别把私钥/对称密钥塞前端
看似废话,但现实中真的有人这么干:
- 在前端写死一个对称密钥;
- 或者把私钥打进前端代码。
这两种做法都等于「没加密」,只会增加维护成本。
对称密钥和私钥都应该只存在于受控后端环境里。
5. HTTPS + 前端加密的边界
前端加密能防什么?
- 防止敏感字段明文出现在抓包/中间日志里;
- 满足某些「应用层加密」的合规要求;
- 在后端内部链路转发时,即使某一环节日志没做好脱敏,也能减轻泄露影响。
它不能防什么?
- 不能防止前端代码被调试、篡改(因为代码在用户手里);
- 不能单独依赖它做「反爬/防脚本登录」;
- 不能取代服务端的登录限流、风控、二次校验等安全手段。
所以把它当成:
安全体系里的一个「配角」,而不是主角。
6. 实战小 Checklist
如果你准备在前端上加一层加密,可以过一遍这个小清单:
- 业务/合规到底要求保护哪些字段?
- 是否已经有统一的「加密服务」接口(公钥下发、密钥轮换)?
- 前端是否使用成熟的加密库,还是要考虑国密算法?
- 是否评估过性能(尤其是移动端)?
- 错误处理是否友好(加密失败、配置获取失败)?
- 日志里是否避免输出密文原文、避免泄露敏感上下文?
7. 总结
前端加解密这个话题很容易被走极端:要么觉得「完全没用」,要么什么都想加密。
比较理性的做法是:
- 先确认业务和合规的真实诉求;
- 在 HTTPS 的基础上,对关键敏感字段加一层应用层保护;
- 用对称 + 非对称组合处理好「性能 vs 安全」;
- 避免自创算法,用成熟方案 + 足够的工程防守。
最后再强调一遍:安全永远是一个整体方案,前端加密只是其中一环,做对了能加分,做错了只能徒增复杂度。