Check user when email and password are in separate tables. Cakephp

Form accepts by email and pw

<?= $this->Form->create() ?>
<?= $this->Form->control('email') ?>
<?= $this->Form->control('password') ?>
<?= $this->Form->button('Login') ?>
<?= $this->Form->end() ?>

      

The email is stored as a user id and the password is stored in the password table Address is an attribute in the email table that stores the actual email address Password is where pw is the stores

The authentication component accepts an address - which

$this->loadComponent('Auth', [
        'authenticate' => [
            'Form' => [
                'fields' => [
                    //here we define what is compared to be authenticated
                    'username' => 'address',    
                    'password' => 'password'
                ]
            ]...

      

The login function is similar to the regular one:

public function login()
{
    if ($this->request->is('post')) {

        //PUT IN STUFF HERE
        $user = $this->Auth->identify();


        if ($user) {
            $user->last_login = Time::now();//dont put this above uif statement, will automatically create a default object
            $this->Auth->setUser($user);
            $this->Flash->success('You have been successfully logged in.');
            $this->log("Login success", 'debug');
          //redirect after login
            return $this->redirect($this->Auth->redirectUrl('/users/index'));
        }
        $this->Flash->error('Your username or password is incorrect.');
        $this->log("Login FAILURE", 'debug');
    }
}`

      

The way I see it we are either comparing the email id or getting a form to directly view the "Associated Classes" attribute. How can one point the authentication to an attribute in another table such as

thank

+3


source to share


2 answers


I would suggest a less intrusive way, that is, use a custom search that contains / concatenates the users table, and sets the field password

in the main query using the alias or main object as a virtual field, this way the inline authenticator fetch the data it needs, which is all it has value for the authenticator.

For example, in your class, EmailsTable

add a crawler like this that picks the correct value for the field password

:

public function findAuth(\Cake\ORM\Query $query, array $options)
{
    return
        $this
            ->find()
            ->select([
                'Emails.id',
                'Emails.address', // you may want to alias this one too
                'password' => 'Users.password'
            ])
            ->leftJoinWith('Users')
            ->where([
                // the options is always named `username`, this is
                // not affected by the `fields` configuration
                'Emails.address' => $options['username']
            ]);
}

      

With a search like this, all you have to do is configure the parameters fields

, userModel

and finder

for the auth component, for example:

$this->loadComponent('Auth', [
    'authenticate' => [
        'Form' => [
            'fields' => [
                // set the field to `email`, just like in your form
                'username' => 'email'
            ],
            'userModel' => 'Emails',
            'finder' => 'auth'
        ]
        // ...
    ]
]);

      



This example assumes that it Emails

is linked Users

through an association belongsTo

or hasOne

using a strategy join

.

Also note that the field is username

set to a value email

exactly the same as in your example form, you can also set as address

(or whatever you really like), this will not affect the search query as it creates a new query and uses the username value that was retrieved from the request data via the configured field (the retrieved value will always be passed to username

) of the array $options

, unless it finder

is an array that already has a named key username

).

see also

+1


source


You need to create Custom Authentication Objects for this

Boot component

$this->loadComponent('Auth', [
        'authenticate' => [
            'CustomForm' => [
                'fields' => [
                    'username' => 'address',// Field in your emails table
                    'password' => 'password',// Field in your users table
                    'myAssoc'=>'Users'// Custom Filed to get association
                ],
                'userModel' => 'Emails'
            ]...

      

Create a CustomFormAuthenticate.php file in / src / Auth / folder

<?php

namespace App\Auth;

use Cake\Auth\FormAuthenticate;
use Cake\Utility\Inflector;

class CustomFormAuthenticate extends FormAuthenticate
{
    public function _findUser($username, $password = null)
    {
        $result = $this->_query($username);
        $myAssoc = false;
        if (!empty($this->_config['fields']['myAssoc'])) {
            $myAssoc = $this->_config['fields']['myAssoc'];
            $result->contain([$myAssoc]);
        }

        $result = $result->first();

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

        if ($password !== null) {
            $hasher = $this->passwordHasher();
            if($myAssoc !== false){
                $hashedPassword = $result->{Inflector::underscore(Inflector::singularize($myAssoc))}[$this->_config['fields']['password']];
            } else {
                $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']);
        }
        debug($result);
        return $result->toArray();
    }

}

      



Make sure you have an email model user association in your EmailTable.php

$this->hasOne('Users', [
    'foreignKey' => 'email_id'
]);

      

On the login page

<?= $this->Form->create() ?>
<?= $this->Form->control('address') ?> // Field in your email table
<?= $this->Form->control('password') ?>// Field in your users table
<?= $this->Form->button('Login') ?>
<?= $this->Form->end() ?>

      

I tested it and it worked for me.

+3


source







All Articles