【问题标题】:How do I replace the cakephp password hashing algorithm?如何替换 cakephp 密码哈希算法?
【发布时间】:2009-02-21 16:20:22
【问题描述】:

我有一个现有的数据库,我正试图在上面放置一个蛋糕应用程序。旧应用程序在 Perl 中使用 crypt() 来散列密码。我需要在 PHP 应用程序中做同样的事情。

在标准 cakephp 应用程序中进行更改的正确位置在哪里?这样的变化会是什么样子?

【问题讨论】:

    标签: php authentication cakephp crypt


    【解决方案1】:

    我搞定了……

    这是我的 AppController:

    class AppController extends Controller {
        var $components = array('Auth');
    
        function beforeFilter() {
            // this is part of cake that serves up static pages, it should be authorized by default
            $this->Auth->allow('display');
            // tell cake to look on the user model itself for the password hashing function
            $this->Auth->authenticate = ClassRegistry::init('User');
            // tell cake where our credentials are on the User entity
            $this->Auth->fields = array(
               'username' => 'user',
               'password' => 'pass',
            );
            // this is where we want to go after a login... we'll want to make this dynamic at some point
            $this->Auth->loginRedirect = array('controller'=>'users', 'action'=>'index');
        }
    }
    

    那么这里是用户:

    <?php
    class User extends AppModel {
        var $name = 'User';
    
        // this is used by the auth component to turn the password into its hash before comparing with the DB
        function hashPasswords($data) {
             $data['User']['pass'] = crypt($data['User']['pass'], substr($data['User']['user'], 0, 2));
             return $data;
        }
    }
    ?>
    

    我认为其他一切正常。

    这是一个很好的资源:@​​987654321@

    【讨论】:

      【解决方案2】:

      实际上,上面描述的 danb 方法在 CakePHP 2.x 中对我不起作用 相反,我最终创建了一个自定义身份验证组件来绕过标准哈希算法:

      /app/Controller/Component/Auth/CustomFormAuthenticate.php

      <?php
      App::uses('FormAuthenticate', 'Controller/Component/Auth');
      
      class CustomFormAuthenticate extends FormAuthenticate {
      
          protected function _password($password) {
              return self::hash($password);
          }
      
          public static function hash($password) {
              // Manipulate $password, hash, custom hash, whatever
              return $password;
          }
      }
      

      ...然后在我的控制器中使用它...

      public $components = array(
          'Session',
          'Auth' => array(
              'authenticate' => array(
                  'CustomForm' => array(
                      'userModel' => 'Admin'
                  )
              )
          )
      );
      

      最后一个块也可以放在 AppControllerbeforeFilter 方法中。就我而言,我只是选择将它专门放在一个控制器中,我将在其中使用具有不同用户模型的自定义身份验证。

      【讨论】:

      • 文件名必须是 CustomFormAuthenticate.php - 而不是 CustomFormAuthentication.php
      • @jesal 我知道这是一个 5 个月大的线程,但是如果我需要使用带有电子邮件作为盐的密码,你知道如何构建 CustomFormAuthenticate 类吗?显然,此时无法访问电子邮件?请帮忙!
      • @rizalp1 我认为您必须将电子邮件从模型的 beforeSave 回调传递到自定义哈希函数:gist.github.com/4689966 - 然后当然在您的自定义函数中您可以做一些事情比如:返回 crypt($password,$email);希望有帮助!
      • 感谢@jesal 我无法直接修改自定义哈希方法,但我覆盖了 CustomFormAuthenticate 中的 authenticate() 方法并使用 $request 获取用户名,并将其保存到属性中。不确定这是否是最好的方法,但它有效!再次感谢:)
      【解决方案3】:

      为了在 CakePHP 2.4.1 中跟进这一点,我正在为一个遗留数据库构建一个前端,该数据库将现有用户密码存储为 md5(accountnumber:statictext:password),并允许用户登录我们需要也使用该哈希系统。

      解决办法是:

      使用以下命令创建文件 app/Controller/Component/Auth/CustomAuthenticate.php:

      <?php
      App::uses('FormAuthenticate', 'Controller/Component/Auth');
      
      class CustomAuthenticate extends FormAuthenticate {
      
          protected function _findUser($username, $password = null) {
              $userModel = $this->settings['userModel'];
              list(, $model) = pluginSplit($userModel);
              $fields = $this->settings['fields'];
      
              if (is_array($username)) {
                  $conditions = $username;
              } else {
                  $conditions = array(
                      $model . '.' . $fields['username'] => $username
                  );
      
              }
      
              if (!empty($this->settings['scope'])) {
                  $conditions = array_merge($conditions, $this->settings['scope']);
      
              }
      
              $result = ClassRegistry::init($userModel)->find('first', array(
                  'conditions' => $conditions,
                  'recursive' => $this->settings['recursive'],
                  'contain' => $this->settings['contain'],
              ));
              if (empty($result[$model])) {
                  return false;
              }
      
              $user = $result[$model];
              if ($password) {
                  if (!(md5($username.":statictext:".$password) === $user[$fields['password']])) {
                      return false;
                  }
                  unset($user[$fields['password']]);
              }
      
              unset($result[$model]);
              return array_merge($user, $result);
          }
      
      }
      

      “扩展 FormAuthenticate”意味着这个文件接管了 _findUser 函数,但对所有其他函数正常地遵循 FormAuthenticate。然后通过编辑 AppController.php 并将其添加到 AppController 类中来激活它:

      public $components = array(
          'Session',
          'Auth' => array(
              'loginAction' => array('controller' => 'accounts', 'action' => 'login'),
              'loginRedirect' => array('controller' => 'accounts', 'action' => 'index'),
              'logoutRedirect' => array('controller' => 'pages', 'action' => 'display', 'home'),
              'authenticate' => array (
                  'Custom' => array(
                      'userModel' => 'Account',
                      'fields' => array('username' => 'number'),
                  )
              ),
          )
      );
      

      特别注意关联数组键“自定义”的使用。

      最后,在创建新用户时需要对密码进行哈希处理,所以我在模型文件(在我的情况下为 Account.php)中添加了:

      public function beforeSave($options = array()) {
          if (isset($this->data[$this->alias]['password'])) {
              $this->data[$this->alias]['password'] = md5($this->data[$this->alias]['number'].":statictext:".$this->data[$this->alias]['password']);
          }
          return true;
      }
      

      【讨论】:

      • 非常感谢@sverreg!多亏了您的回复,我才能使我的密码过程正常工作!
      • 此外,这个解决方案让我们选择将处理身份验证过程的模型。
      • 很高兴有帮助:-)