JavaScript中不能真正加密密码,只能用哈希函数做单向摘要;前端哈希仅为辅助,关键须服务端用bcrypt/Argon2等强算法加盐慢哈希,并强制HTTPS传输。

JavaScript 中不能真正“加密”密码,只能用哈希函数做单向摘要——这是保护用户密码的核心原则。前端哈希只是辅助手段,关键必须配合服务端安全存储(如 bcrypt、Argon2),且绝不能跳过服务端校验。
为什么不能在前端“加密”密码?
客户端代码完全暴露,任何所谓“加密”(比如 base64、简单异或、甚至 AES)都可被逆向或绕过。攻击者抓包就能拿到原始密码或密钥。哈希的不可逆性才是唯一合理选择。
使用 Web Crypto API 做安全哈希(现代推荐)
浏览器原生支持 SHA-256、SHA-512 等标准算法,比手写或第三方库更可信、更高效:
- 先将密码转为 ArrayBuffer(用 TextEncoder)
- 调用 crypto.subtle.digest() 计算哈希值
- 把结果转为十六进制字符串便于传输和比对
示例(SHA-256):
立即学习“Java免费学习笔记(深入)”;
async function hashPassword(password) {
const encoder = new TextEncoder();
const data = encoder.encode(password);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
务必加盐(salt)——但前端盐不安全
单纯哈希易受彩虹表攻击。理想做法是:服务端生成随机 salt,与密码拼接后哈希。前端可做一次预哈希(如 hash(用户名 + 密码)),但不能替代服务端加盐哈希。若必须前端加盐,salt 应动态生成并随请求发送(仍需服务端二次处理)。
避免这些常见错误
- 不用 MD5、SHA-1:已被证明不安全,碰撞容易
- 不用纯前端 bcrypt 或 scrypt:它们依赖大量计算,在浏览器中性能差且无法保证参数强度
- 不把哈希当密码传给后端就完事:后端必须用强哈希(如 bcrypt)重新处理,再比对
- 不忽略 HTTPS:明文密码或哈希在传输中泄露,一切防护归零
哈希不是银弹,而是纵深防御的一环。重点始终是:前端尽量减少明文暴露,服务端用强算法+随机盐+慢哈希,再配合速率限制和多因素认证。











