2013-01-05 44 views
4

谷歌沒有太多的解決方案(similar question but no answer)。Zend 2 Auth與Bcrypt?

由於bcrypt每次都會生成一個新的散列,所以認證失敗。我研究過代碼(可能是自己擴展類),但它非常混亂(更喜歡本地解決方案)。我如何使用$bcrpt->verify()$identity->isValid()

編輯:現在,我已經分類了認證DbTable類,它工作,但我非常懷疑它的優化/「完全正確」。仍在尋找「優雅」的解決方案。

+1

ZF2有一個Bcrypt包裝,但沒有提供Brypt auth適配器,這確實是一件可疑的事情。 – markus

回答

4

正如你應該知道的,BCrypt使用鹽進行散列。每次隨機生成一次鹽。如果您的數據庫受到威脅,這大大增加了查找所有密碼的難度。因此,實際上,每次都會生成一個新的散列。

我自己的問題解決方案是有我自己的Zend\Authentication適配器,它將從數據庫中檢索用戶模型(使用用戶名/電子郵件),然後調用$user->checkPassword($credential);。該方法將獲得Zend\Crypt\Password\Bcrypt的實例。這可以簡單地在給定密碼上調用$bcrypt->verify(),並在用戶模型中調用哈希。

+2

我也有類似的問題, @kokx我們如何做到這一點? 請你舉個例子。 –

13

您可以使用:

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); 
// ... 
+1

偉大的解決方案,非常整齊。謝謝! – MrNorm

+1

這應該是接受的答案很乾淨,並且像魅力一樣工作! – leonziyo

+0

它應該是標準的! – Michael

1

我已經做了這樣的(測試代碼和它的作品)..;

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'; 
        } 
       } 
      } 
     } 
+0

這不可能是正確的方法! – Abadis

+0

首先,您正在進行額外的數據庫調用,使用第一次數據庫調用中的散列檢查用戶輸入的密碼,然後使用第一次數據庫調用中的散列使用第二次數據庫調用時使用數據庫中的散列進行驗證。 這將工作,但它不是正確的方法。我認爲@bigBen提供的解決方案是正確的。 –