In my present system I need to login using username or email and password.
can anybody knows how to achieve this ?
My Form:
<?php echo $this->Form->create('User', array('action' => 'login'));
echo $this->Form->input('username', array('class' => 'TextField js-user-mode'));
echo $this->Form->input('password', array('class' => 'TextField'));
?>
MY AppController:
public $components = array(
'Email'=>array(),
'Auth' => array(
'loginAction' => array(
'admin' => false,
'controller' => 'users',
'action' => 'login'
),
'authError' => 'Your session has ended due to inactivity. Please login to continue.',
'authenticate' => array(
'Form' => array(
'fields' => array('username' => array('username','email')),
),
'all' => array(
'userModel' => 'User',
'scope' => array('User.status' =>array('active'))
)
)
)
);
Let me know what else i need to do..??
I'm not sure what the etiquette is on posting answers to old questions but here's what I did for this.
In my login function
$username = $this->data['User']['username'];
$password = $this->request->data['User']['password'];
$user = $this->User->findByUsername($username);
if (empty($user)) {
$user = $this->User->findByEmail($username);
if (empty($user)) {
$this->Session->setFlash(__('Incorrect Email/Username or Password'));
return;
}
$this->request->data['User']['username'] = $user['User']['username'];
}
I found following code from this url. I think this is the best in sense of simplicity. Use following code on your login action:
public function login() {
if($this->request->is('post')&&!empty($this->request->data)) {
App::Import('Utility', 'Validation');
if( isset($this->data['User']['username']) && Validation::email($this->request->data['User']['username'])) {
$this->request->data['User']['email'] = $this->request->data['User']['username'];
$this->Auth->authenticate['Form'] = array('fields' => array('username' => 'email'));
}
if($this->Auth->login()) {
/* login successful */
$this->redirect($this->Auth->redirect());
} else {
/* login unsuccessful */
}
}
}
And also use following code for login.ctp :
<?php
echo $this->form->create('User');
echo $this->form->input('username');
echo $this->form->input('password');
echo $this->form->end('Submit');
?>
Simply we can do this before your Auth login action:
$emailUsername = #$this->request->data['User']['email'];
if (!filter_var($emailUsername, FILTER_VALIDATE_EMAIL)) {
$emailFromUsername = $this->User->find('first', array('conditions' => array('User.username' => $emailUsername), 'recursive' => -1, 'fields' => array('email')));
//pr($emailFromUsername );
if (!empty($emailFromUsername)) {
$emailFromUsernameDB = $emailFromUsername['User']['email'];
} else {
$emailFromUsername = '';
}
$this->request->data['User']['email'] = $emailFromUsername;
}
Assuming you have username and email both fields in your users table
In your AppController.php
public function beforeFilter() {
if ($this->request->is('post') && $this->action == 'login') {
$username = $this->request->data['User']['username'];
if (filter_var($username, FILTER_VALIDATE_EMAIL)) {
$this->Auth->authenticate['Form']['fields']['username'] = 'email';
$this->request->data['User']['email'] = $username;
unset($this->request->data['User']['username']);
}
}
}
This code will work for CakePHP 2.x, not tested on version 3.x, you should have email field in your user's table.
You can leverage the MultipleColumn Auth adapter:
https://github.com/ceeram/Authenticate/blob/master/Controller/Component/Auth/MultiColumnAuthenticate.php
Update:
New version # https://github.com/dereuromark/cakephp-tools/blob/master/src/Auth/MultiColumnAuthenticate.php
I found this solution useful.
I have created two classes that extend FormAuthenticate:
app/Controller/Component/Auth/ClassNameAuthenticate.php and
<?php
App::uses('FormAuthenticate', 'Controller/Component/Auth');
class ClassNameAuthenticate extends FormAuthenticate {
}
app/Controller/Component/Auth/ClassNameEmailAuthenticate.php
<?php
App::uses('FormAuthenticate', 'Controller/Component/Auth');
class ClassNameEmailAuthenticate extends FormAuthenticate {
}
then in my Controller added Auth Component to $components
public $components = array(
'Session',
'Auth' => array(
'authenticate' => array(
'ClassName' =>array(
'userModel'=>'ClassName',
'fields' => array(
'username' => 'username',
),
'scope' => array('ClassName.active' => 1)
),
'ClassNameEmail' =>array(
'userModel'=>'ClassName',
'fields' => array(
'username' => 'email',
),
'scope' => array('ClassName.active' => 1)
)
)
),
);
login view: login.ctp
<div class="form">
<?php echo $this->Form->create('ClassName'); ?>
<fieldset>
<legend><?php echo __('Login'); ?></legend>
<?php
echo $this->Form->input('username');
echo $this->Form->input('password');
?>
</fieldset>
<?php echo $this->Form->end(array('label'=>__('Login'))); ?>
</div>
and login() action:
public function login(){
if ($this->Auth->loggedIn()) {
return $this->redirect($this->Auth->redirect());
}
if ($this->request->is('post')) {
//Need to duplicate field email for ClassNameEmail Auth
$this->request->data['ClassName']['email'] = $this->request->data['ClassName']['username'];
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
}
$this->Session->setFlash(__('Invalid username/email or password, try again'));
}
}
I hope someone will find this useful.
this is my solution to solve that problem
public function login(){
if($this->request->is('post')){
$this->User->set($this->request->data);
if($this->User->validates()){
if(Validation::email($this->data['User']['username'])){
$this->Auth->authenticate['Form'] = array_merge($this->Auth->authenticate['Form'],array('fields'=>array('username'=>'email')));
$this->request->data['User']['email'] = $this->request->data['User']['username'];
unset($this->request->data['User']['username']);
}
if($this->Auth->login()){
$this->User->id = $this->Auth->user('id');
$this->User->saveField('last_login',time());
if($this->data['User']['remember']){
unset($this->request->data['User']['remember']);
$this->request->data['User']['password'] = Security::hash($this->request->data['User']['password'],'blowfish');
$this->Cookie->write('rememberMe',$this->request->data['User'],true,'2 days');
}
$this->redirect($this->Auth->loginRedirect);
}
$this->Session->setFlash('Invalid Username or Password entered, please try again.','default',array('class'=>'alert alert-warning'),'warning');
}
}
$this->set('title','Login Page');
}
Related
I am wrestling with CakePHP trying to create a basic login functionality. So far CakePHP is winning. I followed the basic Blog tutorial and based on that I am try to create a similair login thingy.
The only difference I have is that I not using an Users model, but a custom Employers model and I use email/password instead of username/password.
Yet all I get is "Your username or password was incorrect."
AppController.php
App::uses('Controller', 'Controller');
class AppController extends Controller {
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array(
'controller' => 'schedules',
'action' => 'index'
),
'logoutRedirect' => array(
'controller' => 'employers',
'action' => 'login',
'home'
),
'authenticate' => array(
'Form' => array(
'fields' => array(
'username' => 'email',
'password' => 'password'
),
'userModel' => 'Employer',
'passwordHasher' => 'Blowfish'
)
)
)
);
}
EmployersController.php
<?php
App::uses('AppController', 'Controller');
class EmployersController extends AppController {
public $helpers = array('Form');
public function beforeFilter()
{
parent::beforeFilter();
$this->Auth->allow('login');
}
public function login()
{
$layout = 'login';
$this->layout = $layout;
if($this->request->is('post'))
{
debug($this->Auth->login());
if($this->Auth->login())
{
return $this->redirect($this->Auth->redirect());
}
else
{
$this->Session->setFlash('Your username or password was incorrect.');
}
debug($this->request->data['Employers']['password']);
}
}
}
Login.ctp
<div id="login-container">
<h1>Login</h1>
<?php
echo $this->Form->create('Employers');
echo $this->Form->input('email', array('label' => false, 'placeholder' => 'Email'));
echo $this->Form->input('password', array('label' => false, 'placeholder' => 'Password'));
echo $this->Form->submit();
echo $this->Form->end();
?>
When I debug $this->request->data, the data is structered like data["Employers"]['email'] & data["Employers"]['password']. This is propably not right, since my model is called Employer.
Is this correct and does the login functionality break on this and if so, how can I fix that?
Or is there something else I am overlooking.
In your login.ctp,
It should be echo $this->Form->create('Employer'); not with s, so remove s and try it.
Hope it helps.
I have developed authentication mechanism in cakePHP prior to this successfully however this time i don't know what is wrongand every time I will be prompted wrong user name/password. I have used Auth component and here are details:
Model names: User,License
sample user info: username: ahmad_agha password:e10adc3949ba59abbe56e057f20f883e which is md5 of 123456
I don't know if it is important in this case or not, but i have enabled admin routing for my controllers.
AppController.php:
class AppController extends Controller {
public $components = array('DebugKit.Toolbar',
'Auth' => array(
'authenticate' => array(
'Form' => array(
'passwordHasher' => array(
'className' => 'Simple',
'hashType' => 'sha256'
)
)
)),
'Cookie');
public function beforeFilter() {
Security::setHash('md5');
$this->Auth->loginRedirect = array('controller'
=> 'licenses', 'action' => 'index');
$this->Auth->logoutRedirect = array('controller'
=> 'owners', 'action' => 'login');
$this->Auth->allow('signup', 'confirm', 'login', 'logout', 'notauthorized', 'display');
$this->Auth->authorize = array('controller');
$this->set('loggedIn', $this->Auth->user('id'));
$this->Auth->userScope = array('User.activated' => '1');
parent::beforeFilter();
}
public function isAuthorized($user) {
// Here is where we should verify the role and give access based on role
return true;
}
}
Login.ctp for User's View
<div class="users form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo md5('136112'); ?>
<?php echo $this->Form->create('User', array('action' => 'login')); ?>
<fieldset>
<legend>
<?php echo __('لطفا نام کاربری و کلمه عبور را وارد کنید'); ?>
</legend>
<?php
echo $this->Form->input('username',array('label'=>'نام کاربری'));
echo $this->Form->input('password',array('label'=>'کلمه عبور'));
echo $this->Form->input('remember_me',array('label'=>'مرا به خاطر بسپار','type'=>'checkbox'));
?>
</fieldset>
<?php echo $this->Form->end(__('ورود')); ?>
</div>
and here is the login() action of UsersController.php:
function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
/* if (!empty($this->data)) {
if (empty($this->data['User']['remember_me'])) {
$this->Cookie->delete('User');
} else {
$cookie = array();
$cookie['username'] = $this->data['User']
['username'];
$cookie['password'] = $this->data['User']
['password'];
$this->Cookie->write('User', $cookie, true, '+2 weeks');
}
unset($this->data['User']['remember_me']);
} */
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
You say your password is md5 hashed while in config for Auth you have set 'hashType' => 'sha256'. So the mismatch of hash types is quite obvious. Setting Security::setHash('md5') isn't going to do anything since the hashtype set in Auth config will take priority.
You need to change the hashType to md5. Also simply saving md5 hash of password in db won't work since password hasher appends a salt (Security.salt specified in your core.php) to the password before hashing. So do (new SimplePasswordHasher)->hash('123456') to get the hashed value which need to be stored in db. All this is explained in the CakePHP manual btw.
I baked a cakephp application with a users table, and I'm trying to get authentication to work using the Blowfish hash. My password field is a varchar(255), so it should be long enough to store the hash. Everything in the app is the default baked output, expect for what follows.
This issue is that I can't log in after creating a user; I always get "Access Denied". What's the best way of troubleshooting this?
AppController.php
App::uses('Controller', 'Controller');
class AppController extends Controller {
public function beforeFilter(){
$this->Auth->allow('index', 'view');
}
public $components = array(
'Session',
'Auth' => array(
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'email'),
'passwordHasher' => 'Blowfish'
)
),
'loginRedirect' => array('controller' => 'users', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'index'),
'authError' => "Access Denied",
'authorize' => array('Controller'),
)
);
public function isAuthorized($user){
return true;
}
}
User.php (model)
App::uses('AppModel', 'Model');
App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth');
public function beforeSave($options = array()) {
if (!empty($this->data['User']['password'])) {
$passwordHasher = new BlowfishPasswordHasher();
$this->data['User']['password'] = $passwordHasher->hash($this->data['User']['password']);
}
return true;
}
UsersController.php
public function login(){
if ($this->request->is('post')) {
if($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
}
else {
$this->Session->setFlash('Access Denied');
}
}
}
login.ctp
echo $this->Form->create('user');
echo $this->Form->input('email');
echo $this->Form->input('password');
echo $this->Form->button('Log In', array('type' => 'submit');
echo $this->Form->end();
'debug($this->request); die;' in login function gives the following output. should password be * or should it be the hashed version of the input?
data => array(
'user' => array(
'password' => '*****',
'email' => 'test#test.com'
)
)
1)listen to #waspinator echo $this->Form->create('User');
2)
App::uses('BlowfishPasswordHasher', 'Controller/Component/Auth');
remove it ad put it in AppController and it should be
App::uses('AuthComponent', 'Controller/Component');
3)comment this lines
//public function beforeFilter(){
// $this->Auth->allow('index', 'view');
//}
//public function isAuthorized($user){
// return true;
//}
4) for first time put this on top of user controller so you can save your password
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('edit', 'index', 'view);
}
echo $this->Form->create('user');
should be
echo $this->Form->create('User');
I created a User with the hash provided by the Cake .. But when I go to log in, says 'Invalid username or password'. But it's all right.
The $this->Auth->login(); always returns false...
Crontroller
class MastersController extends AppController{
public function login(){
if ($this->request->is('post')) {
debug($this->Auth->login());
if ($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
}
else {
$this->Session->setFlash(__('Invalid username or password, try again'));
}
}
}
public function logout(){
$this->redirect($this->Auth->logout());
}}
AppController
class AppController extends Controller {
public $components = array('Session', 'Cookie', 'Auth');
function beforeFilter() {
$this->loadModel('Master');
$this->Auth->userModel = 'Master';
$this->Auth->allow('*');
// Action da tela de login
$this->Auth->loginAction = array(
'masters' => false,
'controller' => 'masters',
'action' => 'login'
);
// Action da tela após o login (com sucesso)
$this->Auth->loginRedirect = array(
'masters' => true,
'controller' => 'masters',
'action' => 'index'
);
// Action para redirecionamento após o logout
$this->Auth->logoutRedirect = array(
'masters' => false,
'controller' => 'pages',
'action' => 'login'
);
$this->Auth->authorize = array('controller');
if (!isset($this->params['masters']) || !$this->params['masters'])
$this->Auth->allow('*','login');
$this->Auth->loginError = __('Usuário e/ou senha incorreto(s)', true);
$this->Auth->authError = __('Você precisa fazer login para acessar esta página', true);
}
public function isAuthorized($masters){
return TRUE;
}}
VIEW login.ctp
echo 'Formulário de login';
echo $this->Session->flash('auth');
echo $this->Session->flash();
echo $this->Form->create('Master', array('controller'=>'masters','action'=>'login'));
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->end('Entrar');
Model
class Master extends AppModel{
public $name = 'Master';
public $validate = array(
'username' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Usuario requerido.'
)
),
'password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Senha requerida.'
)
)
);
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
}
return true;
}
I don't know why it is giving this error .. This all seems ok!
I changed one letter of Security.salt, as he asked ..
Help me :)
I need it for work
debug($this->Auth->login());
if ($this->Auth->login()) {}
is a bad idea.
the first will log you in,
the second call will then - of course - return false (since you are already logged in).
If you really need to test this way, halt the code:
debug($this->Auth->login()); die();
I had the same problem and what fixed it for me was changing $this->alias to User, so beforeSave() now looks like
public function beforeSave($options = array()) {
if (isset($this->data['User']['password'])) {
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
}
return true;
}
I have tried to set up a login page, but when I try to log in, even with a wrong username/password, cake redirects to the login page (the logout function redirects correctly). Even if I plug in the wrong info, I get no error flashes at all, I don't get it. Here is my controller code:
class UsersController extends AppController {
public $name='Users';
public $layout='pagelayout';
public $uses=array('User');
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('add', 'logout', 'overview');
}
public function login() {
$this->set('title', 'Log in to your Gulf Shores 4 Less account');
if ($this->request->is('post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Username or password is incorrect'), 'default', array(), 'auth');
}
}
}
and here is my model:
<?php
App::uses('AuthComponent', 'Controller/Component');
class User extends AppModel {
public $name='User';
public $hasMany=array('Unit', 'Complex', 'Coupon', 'Location', 'Image', 'Charter', 'Course', 'Nightclub', 'Store');
public function beforeSave() {
if (isset($this->data[$this->alias]['password'])) {
$this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
}
return true;
}
public $validate = array(
'username' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A username is required'
)
),
'password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A password is required'
)
),
'role' => array(
'valid' => array(
'rule' => array('inList', array('admin', 'advertiser')),
'message' => 'Please enter a valid role',
'allowEmpty' => false
)
)
);
}
?>
Here is the code from AppController:
<?php
class AppController extends Controller {
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'users', 'action' => 'overview'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'index')
)
);
function beforeFilter() {
$this->Auth->allow('login','index', 'view', 'condos', 'houses', 'hotels_and_motels', 'print_all_coupons', 'print_coupon', 'search', 'golf', 'charters', 'events', 'nightlife', 'shopping', 'visitors_info', 'contact_us');
}
}
?>
and here is the view code:
<div class="users form">
<?php echo $this->Session->flash('auth'); ?>
<?php echo $this->Form->create('User');?>
<fieldset>
<legend><?php echo __('Please enter your username and password'); ?></legend>
<?php
echo $this->Form->input('username');
echo $this->Form->input('password');
?>
</fieldset>
<?php echo $this->Form->end(__('Login'));?>
</div>
As you can see, I pretty much copy and pasted what was in the Cakephp-2.0 manual for this. The only difference between my db table and the manual's is that my password is stored as an MD5 hash in my users table. i can't figure out where this has derailed.
Make sure that your passwords are stored using the Auth component hash. AFAIK, there is no support for 'plain' md5 passwords. The hashes Cake generates are more complex than md5.
See the documentation for info on how to hash your passwords. If you are migrating from an app that used md5 hashing, you'll have to reset all the passwords to something random for all your users.
You can try to use the following codes on your AppController.php file
AppController.php
$this->Auth->authenticate = array(
AuthComponent::ALL => array('userModel' => 'User'),
'Form' => array(
'fields' => array('username' => 'email')
)
);
$this->Auth->authorize =false;
$this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
$this->Auth->fields = array('username' => 'email', 'password' => 'password');
$this->Auth->loginRedirect = array('controller' => 'media', 'action' => 'index/');
$this->Auth->logoutRedirect = '/logout';
$this->Auth->loginError = 'Invalid e-mail / password combination. Please try again';