我试图了解Yii框架2的登录过程。当Security
类使用以下代码行验证密码时,我陷入了困境。
return Yii::$app->security->validatePassword($password, $this->password_hash);
当我查看这个validatePassword()
方法时,它看起来如下。
public function validatePassword($password, $hash)
{
if (!is_string($password) || $password === '') {
throw new InvalidParamException('Password must be a string and cannot be empty.');
}
if (!preg_match('/^'$2[axy]'$('d'd)'$['.'/0-9A-Za-z]{22}/', $hash, $matches) || $matches[1] < 4 || $matches[1] > 30) {
throw new InvalidParamException('Hash is invalid.');
}
switch ($this->passwordHashStrategy) {
case 'password_hash':
if (!function_exists('password_verify')) {
throw new InvalidConfigException('Password hash key strategy "password_hash" requires PHP >= 5.5.0, either upgrade your environment or use another strategy.');
}
return password_verify($password, $hash);
case 'crypt':
$test = crypt($password, $hash);
$n = strlen($test);
if ($n !== 60) {
return false;
}
return $this->compareString($test, $hash);
default:
throw new InvalidConfigException("Unknown password hash strategy '{$this->passwordHashStrategy}'");
}
}
当我查看compareString()
方法时,它看起来如下。
public function compareString($expected, $actual)
{
$expected .= "'0";
$actual .= "'0";
$expectedLength = StringHelper::byteLength($expected);
$actualLength = StringHelper::byteLength($actual);
$diff = $expectedLength - $actualLength;
for ($i = 0; $i < $actualLength; $i++) {
$diff |= (ord($actual[$i]) ^ ord($expected[$i % $expectedLength]));
}
return $diff === 0;
}
我不明白Yii 2是如何获得并使用salt和cost来验证和比较密码和密码哈希的?有资深开发人员知道吗?你能解释一下吗?非常感谢。
默认情况下,Yii2使用password_hash
来存储和验证密码。盐和成本自动包含在password_hash算法中,我们不在乎
password_verify($password, $hash);
参考:http://php.net/manual/en/book.password.php
您可以从yii''base''Security类扩展自己的类,重新定义父方法generateSalt()、generatePasswordHash()、validatePassword(),并在yii应用程序中设置新的Security类:
'components' => [
...
'security' => [
'class' => 'app'components'MySecurity'
],