直接找回密码的风险
数据泄露:如果密码以明文形式存储,一旦数据库被黑客攻破,所有用户的隐私都将暴露无遗。
密码复用:很多用户会在不同的网站上使用相同的密码。如果一个网站直接显示用户的密码,那么这些密码也可能被用于其他网站,导致更大的安全风险。
内部威胁:即使是加密存储的密码,任何允许密码恢复的途径都可能被内部人员滥用,从而危害用户安全。
密码存储的小秘密
应用通常不会直接存储用户的原始密码,而是存储密码的哈希值。哈希是一种单向加密算法,它将任意长度的数据转换成固定长度的字符串,而且这个过程是不可逆的。常用的哈希算法有MD5、SHA-1、SHA-256等。为了增加安全性,通常还会加上盐(salt),即随机生成的一串字符,与密码一起进行哈希运算。常见的哈希算法如下:
哈希算法 | 优点 | 缺点 |
MD5 | 计算速度快,广泛应用于文件完整性校验 | 已经被证明不够安全,容易受到碰撞攻击 |
SHA-1 | 比MD5更安全,曾经是广泛使用的哈希算法 | 已被证明存在安全漏洞,不再推荐用于密码存储 |
SHA-256 | 目前较为安全的哈希算法,广泛应用于各种安全场景 | 虽然比MD5和SHA-1更安全,但在某些情况下仍可能受到攻击 |
Bcrypt | 专门为密码存储设计,具有加盐(salt)机制,可以抵抗彩虹表攻击和预计算攻击 | 计算速度较慢,但这恰恰是它的优势之一,因为它使得暴力破解变得更加困难 |
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class PasswordHashing {
public static void main(String[] args) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String rawPassword = "Password@123"; // 用户注册时输入的原始密码
String encodedPassword = encoder.encode(rawPassword); // 将密码哈希后存储
// saveToDB();
System.out.println(encodedPassword); // 哈希后: $2a$10$69TdV/shNWsJ.3y02KE/reoIcFYaVKrBNW.NqeG0/VFSiwkzWpgT.
// 用户登录时先将用户输入的密码进行哈希,然后与数据库中存储的哈希值进行对比
boolean matches = encoder.matches(rawPassword, encodedPassword);
System.out.println(matches); // 一致则登录成功
}
}
用户输入:用户在登录页面输入用户名和密码。
查找用户:系统会根据用户名查找对应的用户记录。
获取存储的哈希值:从用户记录中获取存储的密码哈希值。
哈希用户输入:使用相同的哈希算法(和加盐值,如果有的话)对用户输入的密码进行哈希。
比较哈希值:将用户输入密码的哈希值与存储的哈希值进行比较。
验证结果:如果两个哈希值匹配,则认证成功;否则,认证失败。
到这里,相信你应该已经理解了为什么系统在用户忘记密码时选择重置而不是直接发送原密码。因为哈希算法是不可逆的,服务端无法通过数据库中存储的哈希值获取到用户的原始密码,所以也就无法发送原密码给你。密码哈希存储不仅提高了系统的安全性,也保护了用户的隐私。作为开发者,我们应该始终关注安全最佳实践,为用户提供更安全的服务体验。