谷歌没有太多的解决方案(类似的问题,但没有答案)。
因为 bcrypt 每次都会生成一个新的哈希,所以认证失败。我已经查看了代码(也许我自己扩展了类),但它非常混乱(更喜欢本机解决方案)。如何使用$bcrpt->verify()
with $identity->isValid()
?
编辑:目前,我已经对身份验证 DbTable 类进行了子类化,并且它正在工作,但我非常怀疑它是否经过优化/“完全正确”。仍在寻找“优雅”的解决方案。
谷歌没有太多的解决方案(类似的问题,但没有答案)。
因为 bcrypt 每次都会生成一个新的哈希,所以认证失败。我已经查看了代码(也许我自己扩展了类),但它非常混乱(更喜欢本机解决方案)。如何使用$bcrpt->verify()
with $identity->isValid()
?
编辑:目前,我已经对身份验证 DbTable 类进行了子类化,并且它正在工作,但我非常怀疑它是否经过优化/“完全正确”。仍在寻找“优雅”的解决方案。
您可以使用:
Zend\Authentication\Adapter\DbTable\CallbackCheckAdapter
像这样 :
use Zend\Authentication\Adapter\DbTable\CallbackCheckAdapter as AuthAdapter;
use Zend\Crypt\Password\Bcrypt;
$credentialValidationCallback = function($dbCredential, $requestCredential) {
return (new Bcrypt())->verify($requestCredential, $dbCredential);
};
$authAdapter = new AuthAdapter($dbAdapter, 'user', 'login', 'password', $credentialValidationCallback);
// ...
如您所知,BCrypt 使用盐进行散列。并且每次都会随机再次生成盐。如果您的数据库遭到破坏,这会大大增加查找所有密码的难度。因此,实际上,它每次都会生成一个新的散列。
对于您遇到的问题,我自己的解决方案是拥有自己的Zend\Authentication
适配器,它将从数据库中检索用户模型(使用用户名/电子邮件),然后调用$user->checkPassword($credential);
. 该方法将获得Zend\Crypt\Password\Bcrypt
. 这将简单地调用$bcrypt->verify()
给定的密码和用户模型中的哈希。
我已经这样做了(测试代码并且有效)..;
if ($request->isPost()) {
$form->setData($request->getPost());
if ($form->isValid()) {
$bcrypt = new Bcrypt();
$user = new User();
$user->exchangeArray($form->getData());
$password = $user->password;
$data = $this->getUserTable()->selectUser($user->username);
if (!$data)
{
echo 'user not found';
} else {
if ($bcrypt->verify($password, $data->hash)) {
$sm = $this->getServiceLocator();
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$authAdapter = new AuthAdapter(
$dbAdapter,
'cms_users',
'username',
'hash'
);
$authAdapter->setIdentity($user->username)
->setCredential($data->hash);
$result = $auth->authenticate($authAdapter);
echo $result->getIdentity() . "\n\n";
// do you thing on succes/failure
} else {
echo 'invalid password';
}
}
}
}