Login with username or email with Cakephp 3

南楼画角 提交于 2020-12-28 21:03:29

问题


I want to do a login with username or email. So I want to change Auth fields dynamically.

How can I modify $this->Auth fields as Cakehp 2 did?

In cakephp 2 you could do:

$this->Auth->authenticate = array(
    'Form' => array(
        'fields' => array('username' => 'email', 'password' => 'password'),
    ),
);

I've tried to change authenticate like this but it doesn't work:

$this->Auth->config('authenticate', [
    'Form' => [
        'fields' => ['username' => 'email', 'password' => 'password']
    ]
]);

Thanks!


回答1:


I've found the solution!

I assumed that username is alphaNumeric (letters and numbers).

Remember to add $this->Auth->constructAuthenticate();

AppController.php

use Cake\Controller\Controller;
use Cake\Event\Event;
use Cake\Core\Configure;

class AppController extends Controller
{
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('Flash');
        $this->loadComponent('Auth', [
            'loginRedirect' => [
                'controller' => 'Users',
                'action'     => 'index'
            ],
            'logoutRedirect' => [
                'controller' => 'Users',
                'action'     => 'login'
            ]
        ]);
    }
}

UsersController.php

use App\Controller\AppController;
use Cake\Validation\Validation;

class UsersController extends AppController
{
    public function login()
    {
        if ($this->request->is('post')) {

            if (Validation::email($this->request->data['username'])) {
                $this->Auth->config('authenticate', [
                    'Form' => [
                        'fields' => ['username' => 'email']
                    ]
                ]);
                $this->Auth->constructAuthenticate();
                $this->request->data['email'] = $this->request->data['username'];
                unset($this->request->data['username']);
            }

            $user = $this->Auth->identify();

            if ($user) {
                $this->Auth->setUser($user);
                return $this->redirect($this->Auth->redirectUrl());
            }

            $this->Flash->error(__('Invalid username or password, try again'));
        }
    }
}

login.ctp

<div class="form">
<?= $this->Flash->render('auth') ?>
<?= $this->Form->create() ?>
    <fieldset>
        <legend><?= __('Please enter your username and password') ?></legend>
        <?= $this->Form->input('username') ?>
        <?= $this->Form->input('password') ?>
    </fieldset>
<?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>
</div>



回答2:


Here is my solution.

AppController.php load Auth component.

$this->loadComponent('Auth', [
        'authorize' => 'Controller',
        'authenticate' => [
            'Form' => [
                'userModel' => 'Users',
            ]
        ],
        ...
    ]);

UsersController.php

Note: identify() method

http://book.cakephp.org/3.0/en/controllers/components/authentication.html#identifying-users-and-logging-them-in

public function login()
{
    if ($this->request->is('post')) {
        //$user = $this->Auth->identify();
        $user = $this->Users->identify($this->request->data);
        if ($user) {
            $this->Auth->setUser($user);
            return $this->redirect($this->Auth->redirectUrl());
        } else {
            $this->Flash->error(__('Username or password is incorrect'), [
                'key' => 'auth'
            ]);
        }
    }
}

UsersTable.php

Assuming that email and username columns are in same table.

use Cake\Auth\DefaultPasswordHasher;

public function identify($formData) {

        $passOk = false;
        $user = $this->find()->hydrate(false)->where(['email' => $formData['email']])->orWhere(['username' => $formData['email']])->first();
        $checker = new DefaultPasswordHasher;
        if(!is_null($passOk))
            $passOk = $checker->check($formData['password'], $user['password']); 

        return $passOk ? $user  : null;

    }



回答3:


log in with the username Or Email its Perfect Work just try it.

UsersController.php

    if($this->request->is('post')){
        if(!filter_var($this->request->data['username'], FILTER_VALIDATE_EMAIL)===false){
            $this->Auth->config('authenticate', [
                'Form'=>['fields'=>['username'=>'email', 'password'=>'password']]
            ]);
            $this->Auth->constructAuthenticate();
            $this->request->data['email']=$this->request->data['username'];
            unset($this->request->data['username']);
        }
        pr($this->request->data);

        $user=$this->Auth->identify();
        if($user){
            $this->Auth->setUser($user);
            $this->Flash->success(__('Wel Come-'.ucfirst($user['name'])));
            return $this->redirect($this->Auth->redirectUrl());
        }
        $this->Flash->error(__('Invalid username or password, try again'));
    }



回答4:


This is another useful solution (perhaps)...

login.ctp

To make your life easy, for the user input just use username and password

<?= $this->Form->create() ?>
     <div class="panel-body">
         <div class="form-group">
             <?= $this->Form->control('username', // <-- username input
               ['type' => 'text', 'class' => 'form-control', 'label' => false, 
                    'placeholder' => __('Username Or Email') ]) ?>
             <?= $this->Form->control('password',  // <-- password input
               ['class' => 'form-control', 'label' => false, 'placeholder' => 
                    __('Password')]) ?>
                        </div>
             <?= $this->Form->button('ログイン', ['class' => 'btn btn-primary btn-block']) ?>
     </div>
<?= $this->Form->end() ?> 

UsersTable.php

Here is the place where we create checking for columns (username or email). While, for password checking, its already taken care by CakePHP, no need to include it here.

use Cake\ORM\Query;  

public function findAuth(Query $query, array $options)
{
    $query->where([
            'OR' => [ //<-- we use OR operator for our SQL
                'username' => $options['username'], //<-- username column
                'email' => $options['username'] //<-- email column
            ]], [], true); // <-- true here means overwrite original query !IMPORTANT. 

    return $query;
}

AppController.php load Auth component.

public function initialize()
{
     parent::initialize();
     $this->loadComponent('Auth', [
            'authenticate' => [
                'Form' => [
                    'finder' => 'auth' //<-- here we call our findAuth methods
                ]
            ],
     ]);
}

That's all. Happy coding. 😊

All the best!

CakePHP 3 reference: https://book.cakephp.org/3.0/en/controllers/components/authentication.html#customizing-find-query



来源:https://stackoverflow.com/questions/30648852/login-with-username-or-email-with-cakephp-3

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