【问题标题】:How to use php 5.5 password api with Zend_Auth_Adapter_DbTable如何在 Zend_Auth_Adapter_DbTable 中使用 php 5.5 密码 API
【发布时间】:2013-07-03 09:48:19
【问题描述】:

到现在为止,我已经以纯文本形式存储了所有密码,因为该网站没有上线,我决定等待新的password api

我有此代码可用于纯文本密码:

<?php
$dbAdapter = Zend_Db_Table::getDefaultAdapter();
$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);

$authAdapter->setTableName('account')
    ->setIdentityColumn('account_id')
    ->setCredentialColumn('account_password');

// Get our authentication adapter and check credentials
$adapter = $authAdapter;
$adapter->setIdentity($values['account_id']);
$adapter->setCredential($values['password']);

$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($adapter);
if ($result->isValid()) {
    $user = $adapter->getResultRowObject();
    $auth->getStorage()->write($user);
    return true;
}
return false;

根据docs,我应该实现自己的适配器,并且可能只是更改为使用password_verify()。

我在这里错过了一切如何协同工作的大图。

我的问题是:

  1. 我应该修改女巫对象吗? $authAdaper$auth

任何高级(或低级:D)示例代码都将不胜感激。

一切顺利 亚当

【问题讨论】:

    标签: php zend-framework zend-auth php-password-hash


    【解决方案1】:

    如果您希望通过添加password_hash 加密来修改身份验证的操作方式,那么 您需要在PHP 内完成此操作。

    由于您仍希望使用数据库身份验证,我认为将其重新创建为新适配器将是矫枉过正。但是,您可以扩展当前的数据库适配器,例如:

    class My_Auth_Adapter_DbTable extends Zend_Auth_Adapter_DbTable
    {
      public function setCredential($credential)
      {
        $this->_credential = password_hash($credential);
        return $this;
      }
    }
    

    这意味着提供给适配器的任何密码都将始终使用password_hash 函数进行加密。

    但是,这可以通过在调用 setCredential 之前对密码进行哈希处理来在适配器外部完成。

    $options  = array('salt' => $config->passwordSalt);
    $hashPassword = password_hash($plainTextPassword, PASSWORD_BCRYPT, $options);
    $adpater->setCredential($hashPassword);
    

    此方法将允许您在传递给适配器之前修改可选参数。

    最后,值得一提的是,setCredentialTreatment 方法通常用于提供密码加密,这是在 SQL 语句中执行的(这意味着您需要使用 MySQL 命令而不是 password_hash)。

    $authAdapter->setTableName('user')
          ->setIdentityColumn('email')
          ->setCredentialColumn('password')
          ->setCredentialTreatment(sprintf("MD5(CONCAT(?,'%s'))", $config->passwordSalt));
    

    【讨论】:

    • $adpater->setCredential($hashPassword);通过这种方式,我需要将盐单独存储在数据库中?
    • 我不需要在任何地方使用 password_verify() 吗??
    • 如果您想对所有密码使用一种盐,那么您可以在application.ini 中定义它。 $config-&gt;passwordSalt 只是一个字符串,$config 是一个 Zend_Config 实例。
    • 您不需要使用password_verify,因为密码匹配将在 SQL 语句中完成。但是,您将需要使用与身份验证时相同的盐和哈希算法对数据库中的所有密码进行哈希处理。
    • 如果我不想单独制作盐,那么您的任何解决方案都不起作用?根据this,你应该让新密码api来处理salt。
    【解决方案2】:

    password_hash() 创建的哈希值需要通过 ̀password_verify()` 进行比较,因为相同密码的 2 个哈希值并不总是相等的(至少不使用 BCRYPT 或 ARGON2)。

    <?php
    $pass = 'foo';
    var_dump(password_hash($pass, PASSWORD_BCRYPT) === password_hash($pass, PASSWORD_BCRYPT));
    // bool(false)
    var_dump(password_verify($pass, password_hash($pass, PASSWORD_BCRYPT)));
    // bool(true)
    

    有人 (s7anley) 做了一个Zend_Auth_Adapter_DbTable extension that uses password_verify(),这里是(供参考):

    <?php
    
    class Base_Auth_Adapter_BcryptDbTable extends Zend_Auth_Adapter_DbTable
    {
        /**
         * @inheritdoc
         */
        protected function _authenticateCreateSelect()
        {
            $dbSelect = clone $this->getDbSelect();
            $dbSelect->from($this->_tableName)
                ->where($this->_zendDb->quoteIdentifier($this->_identityColumn, true) . ' = ?', $this->_identity);
    
            return $dbSelect;
        }
    
        /**
         * @inheritdoc
         */
        protected function _authenticateValidateResult($resultIdentity)
        {
            $passwordCheck = password_verify($this->_credential, $resultIdentity[$this->_credentialColumn]);
    
            if (!$passwordCheck) {
                $this->_authenticateResultInfo['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
                $this->_authenticateResultInfo['messages'][] = 'Supplied credential is invalid.';
                return $this->_authenticateCreateAuthResult();
            }
    
            $this->_resultRow = $resultIdentity;
    
            $this->_authenticateResultInfo['code'] = Zend_Auth_Result::SUCCESS;
            $this->_authenticateResultInfo['messages'][] =  'Authentication successful.';
            return $this->_authenticateCreateAuthResult();
        }
    }
    

    类名显示为“Bcrypt”,但它适用于password_hash() 支持的任何算法。

    你可以这样使用它:

    $authAdapter = new Base_Auth_Adapter_BcryptDbTable($databaseAdapter, 'users', 'login', 'password');
    $authAdapter
        ->setIdentity('my_username')
        ->setCredential('my_password') // "clear" password
        // ->setCredentialTreatment(null) // Can't set any treatment on password (would be ignored)
    ;
    // For any additional filtering of returned rows, use getDbSelect()
    $authAdapter->getDbSelect()->where('active = "TRUE"');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-02
      • 2018-08-31
      • 2018-07-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-03
      • 1970-01-01
      相关资源
      最近更新 更多