使用 Cakephp 3 使用用户名或电子邮件登录

Login with username or email with Cakephp 3

我想使用用户名或电子邮件登录。所以我想动态更改 Auth 字段。

如何像 Cakehp 2 那样修改 $this->Auth 字段?

在 cakephp 2 中你可以这样做:

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

我试过像这样更改身份验证,但它不起作用:

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

谢谢!

我找到了解决办法!

我假设用户名是字母数字(字母和数字)。

记得加$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>

这是我的解决方案。

AppController.php 加载 Auth 组件。

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

UsersController.php

注意:identify() 方法

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

假设 emailusername 列在相同的 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;

    }

使用用户名登录或通过电子邮件发送其 Perfect Work 试试吧。

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'));
    }

这是另一个有用的解决方案(也许)...

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 加载 Auth 组件。

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

就是这样。快乐的编码。

祝一切顺利!

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