Pass extra data to finder auth

只愿长相守 提交于 2019-12-10 02:34:10

问题


My finder from Auth has conditions that I need to access $this->request but I don't have access for that on UsersTable.

AppController::initialize

$this->loadComponent('Auth', [
        'authenticate' => [
            'Form' => [
                'finder' => 'auth',
            ]
        ]
    ]);

UsersTable

public function findAuth(Query $query, array $options)
{
    $query
        ->select([
            'Users.id',
            'Users.name',
            'Users.username',
            'Users.password',
        ])
        ->where(['Users.is_active' => true]); // If i had access to extra data passed I would use here.

    return $query;
}

I need pass an extra data fom AppController to finder auth since I dont have acces to $this->request->data on UsersTable.

Update

People are saying on comments that is a bad design so I will explain exactly what I need.

I have a table users but each user belongs to a gym. The username(email) is unique only to a particular gym so I can have a example@domain.comfrom gym_id 1 and another example@domain.com from gym_id 2. On login page I have the gym_slug to tell to auth finder wich gym the user username that I provied belongs.


回答1:


To my knowledge, there is no way to do this by passing it into the configuration in 3.1. This might be a good idea submit on the cakephp git hub as a feature request.

There are ways to do it by creating a new authentication object that extends base authenticate and then override _findUser and _query. Something like this:

class GymFormAuthenticate extends BaseAuthenticate
{

 /**
  * Checks the fields to ensure they are supplied.
  *
  * @param \Cake\Network\Request $request The request that contains login information.
  * @param array $fields The fields to be checked.
  * @return bool False if the fields have not been supplied. True if they exist.
  */
 protected function _checkFields(Request $request, array $fields)
 {
     foreach ([$fields['username'], $fields['password'], $fields['gym']] as $field) {
         $value = $request->data($field);
         if (empty($value) || !is_string($value)) {
             return false;
         }
     }
     return true;
 }

 /**
  * Authenticates the identity contained in a request. Will use the `config.userModel`, and `config.fields`
  * to find POST data that is used to find a matching record in the `config.userModel`. Will return false if
  * there is no post data, either username or password is missing, or if the scope conditions have not been met.
  *
  * @param \Cake\Network\Request $request The request that contains login information.
  * @param \Cake\Network\Response $response Unused response object.
  * @return mixed False on login failure.  An array of User data on success.
  */
 public function authenticate(Request $request, Response $response)
 {
     $fields = $this->_config['fields'];
     if (!$this->_checkFields($request, $fields)) {
         return false;
     }
     return $this->_findUser(
         $request->data[$fields['username']],
         $request->data[$fields['password']],
         $request->data[$fields['gym']],
     );
 }

/**
  * Find a user record using the username,password,gym provided.
  *
  * Input passwords will be hashed even when a user doesn't exist. This
  * helps mitigate timing attacks that are attempting to find valid usernames.
  *
  * @param string $username The username/identifier.
  * @param string|null $password The password, if not provided password checking is skipped
  *   and result of find is returned.
  * @return bool|array Either false on failure, or an array of user data.
  */
 protected function _findUser($username, $password = null, $gym = null)
 {
     $result = $this->_query($username, $gym)->first();

     if (empty($result)) {
         return false;
     }

     if ($password !== null) {
         $hasher = $this->passwordHasher();
         $hashedPassword = $result->get($this->_config['fields']['password']);
         if (!$hasher->check($password, $hashedPassword)) {
             return false;
         }

         $this->_needsPasswordRehash = $hasher->needsRehash($hashedPassword);
         $result->unsetProperty($this->_config['fields']['password']);
     }

     return $result->toArray();
 }

/**
  * Get query object for fetching user from database.
  *
  * @param string $username The username/identifier.
  * @return \Cake\ORM\Query
  */
 protected function _query($username, $gym)
 {
     $config = $this->_config;
     $table = TableRegistryget($config['userModel']);

     $options = [
         'conditions' => [$table->aliasField($config['fields']['username']) => $username, 'gym' => $gym]
     ];

     if (!empty($config['scope'])) {
         $options['conditions'] = array_merge($options['conditions'], $config['scope']);
     }
     if (!empty($config['contain'])) {
         $options['contain'] = $config['contain'];
     }

     $query = $table->find($config['finder'], $options);

     return $query;
 }
 }

For more information see this: Creating Custom Authentication Objects




回答2:


I know this is an old question but I thought I would post the finder I am using in one of our SaaS apps built on Cakephp 3. Does it follow DRY etc probably not. To say everything can be done X or Y way ..... you always have to bend the rules. In this case depending on the URL (xdomain.com or ydomain.com) our app figures out who the customer is and changes layouts etc. Also the user based is tied to Email & site_id much like yours

public function findAuth(\Cake\ORM\Query $query, array $options) {
    $query
            ->select([
                'Users.id',
                'Users.email',
                'Users.password',
                'Users.site_id',
                'Users.firstname',
                'Users.lastname'])
            ->where([
                'Users.active' => 1,
                'Users.site_id'=> \Cake\Core\Configure::read('site_id')
            ]);

    return $query;
}

Anyway hope it helps someone



来源:https://stackoverflow.com/questions/33272426/pass-extra-data-to-finder-auth

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!