你有没有想过,你在某个网站注册的账号密码,可能正被人用记事本打开浏览?别觉得夸张,现实中真有不少小公司或个人开发者把用户密码直接以明文形式存进数据库。
明文存储有多危险?
想象一下,你的服务器被拖库了,黑客拿到整张用户表,用户名、邮箱、密码清清楚楚。更惨的是,很多人在多个网站用同一套密码。一旦泄露,不只是这个账号完蛋,连带邮箱、支付宝、微博都可能被撞库攻破。
所以,服务端绝不能明文存密码。这不是高深技术,而是基本底线。
用哈希加密是第一步
最简单的改进方式是用哈希函数处理密码,比如 SHA-256。用户注册时,把密码先哈希再存库。
password_hash = SHA256("user_input_password")
登录时,同样对输入密码做哈希,比对数据库里的值。这样即使数据泄露,黑客也看不到原始密码。
但普通哈希还不够
问题来了,SHA-256 是固定输出,同样的密码永远生成一样的哈希值。黑客可以提前算好常见密码的哈希值,做成“彩虹表”,直接反查。
解决办法是加“盐”(salt)。每个用户生成一个随机字符串,拼到密码前面再哈希。盐值和哈希结果一起存库。
salt = "随机生成的字符串,如: xk3m9p2n"
hashed = SHA256(salt + "123456")
这样一来,同一个密码,不同用户的哈希值完全不同,彩虹表就失效了。
推荐使用专用算法
自己拼 salt 和哈希容易出错,建议直接用现成的安全算法。比如 bcrypt、scrypt 或 Argon2。它们内置了盐值和多次迭代,抗暴力破解能力强。
以 bcrypt 为例,Node.js 中可以这样写:
const bcrypt = require('bcrypt');
// 注册时加密
const saltRounds = 10;
const hash = await bcrypt.hash(password, saltRounds);
// 登录时验证
const match = await bcrypt.compare(inputPassword, hash);
Python 的 Flask 用户可以用 werkzeug:
from werkzeug.security import generate_password_hash, check_password_hash
# 加密
hash = generate_password_hash('my_password')
# 验证
check_password_hash(hash, 'my_password')
别再用 MD5 或 SHA-1
这些老算法太快了,GPU 一秒钟能跑几亿次,根本不防暴力破解。现在正规项目都该用慢一点、专门设计来保护密码的算法。
额外提醒:传输过程也要加密
就算你存得再安全,如果用户登录时走的是 HTTP 明文传输,中间人一样能截获密码。务必开启 HTTPS,给传输层加上 SSL/TLS 加密。
说白了,用户把密码交给你,就是一种信任。别因为省事,把这份信任放在裸奔的数据库里。