问题
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