PHP 安全:绝不明文保存用户密码
背后的原因
常有人告诉你不要明文保存用户的密码,因为那会带来可怕的安全隐患。但很少有人告诉你真正的原因是什么。
有人问我:“假设我是一个黑客,我已经黑入了网站的数据库,获取到了所有的数据。那密码加密与否还重要吗?”。
但其实,这是一个误会。直接黑入数据库并不是唯一的访问数据库的方式,很多其他方式(如:SQL 注入攻击)都可以在不进入数据库的情况下获取到你的数据。
而加密保存密码则可以确保他人使用非法手段拿到密码之后,仍无法解密和使用。
明文保存带来的隐患
一个前提是,黑客入侵通常是无影无踪的,并不会像电影里那样留下一段信息,很嚣张地说我来过这,感谢你提供的数据。大部分的入侵通常都悄无声息地进行,你很难去发现它,更加无法及时通知你的用户更换密码。
一个成熟网站的用户数量可不在少数,即便你很快发现了数据泄露的发生,你也无法确保在短时间内通知所有用户,让他们更改密码。而在这期间,已经足够黑客完成许多事。
另一方面,我们无法确保用户会在我们的网站上使用独一无二的密码。大部分用户都只有一个密码,用于几乎所有站点的登入。一旦这密码在你的网站上泄露,可能意味着他们所有账户的沦陷。
除此之外,明文保存的另一要点是,你(或有权访问数据库的所有人)都能直接看到用户的密码。以用户的角度设想,我绝不会允许某个网站知道我的密码,那毫无疑问属于我的隐私。
正确的密码保存方式
我强烈建议你将密码以现代的加密方式存储,例如 bcrypt
、argon
等加密算法。
在 PHP5.5 的时候,PHP 就引入了 password_hash
和 password_verify
函数,用于密码的加密和校验。除非你有特别的需要,否则我一律建议你使用这两函数作为你的密码加密方式。
链式哈希!绝妙的点子?
不,绝不!你可能会觉得 md5(sha1($password))
这种方式可以大大的增强密码的安全性,因为它经过了两次的处理。但实际上,这是完全错误,且不应使用的。
对于链式哈希来说,它的安全性一般等于或小于最弱算法的安全性。例如 md5(sha1($password))
并不会比 sha1($password)
更加安全。因此这种加密除了自欺欺人之外是没有任何意义的。
总结
对于大部分应用,我都建议你使用 password_hash
和 password_verify
进行密码储存的步骤。