php常见安全问题实例讲解( 三 )


另外一个比较重要的点是你应该为密码哈希加盐(Salt),加盐处理避免了两个同样的密码会产生同样哈希的问题 。
以下使用 MD5 来做例子,所以请千万不要使用 MD5 来哈希你的密码, MD5 是不安全的 。
假如我们的用户 user1 和 user315 都有相同的密码 ilovecats123,这个密码虽然看起来是强密码,有字母有数字,但是在数据库里,两个用户的密码哈希数据将会是相同的:5e2b4d823db9d044ecd5e084b6d33ea5。
如果一个如果黑客拿下了你的网站,获取到了这些哈希数据,他将不需要去暴力破解用户 user315 的密码 。我们要尽量让他花大精力来破解你的密码,所以我们对数据进行加盐处理:
<?php
//warning: !!这是一个很不安全的密码哈希例子,请不要使用!!
$password = 'cat123';
$salt = random_bytes(20);
$hash = md5($password . $salt);
最后在保存你的唯一密码哈希数据时,请不要忘记连 $salt 也已经保存,否则你将无法验证用户 。
在当下,最好的密码哈希选项是 bcrypt,这是专门为哈希密码而设计的哈希算法,同时这套哈希算法里还允许你配置一些参数来加大破解的难度 。
新版的 PHP 中也自带了安全的密码哈希函数 password_hash ,此函数已经包含了加盐处理 。对应的密码验证函数为 password_verify 用来检测密码是否正确 。password_verify 还可有效防止 时序攻击.
以下是使用的例子:
<?php
//user signup
$password = $_POST['password'];
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
//login
$password = $_POST['password'];
$hash = '1234'; //load this value from your db
if(password_verify($password, $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
需要澄清的一点是:密码哈希并不是密码加密 。哈希(Hash)是将目标文本转换成具有相同长度的、不可逆的杂凑字符串(或叫做消息摘要),而加密(Encrypt)是将目标文本转换成具有不同长度的、可逆的密文 。显然他们之间最大的区别是可逆性,在储存密码时,我们要的就是哈希这种不可逆的属性 。




推荐阅读