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.
Related
Good Morning,
I have got issue with login into my web application.
When I'm registering on my app there is no error (In my opinion):
//Register
public function register() {
$user = $this->Users->newEntity();
if($this->request->is('post')) {
$this->request->data('status', '0');
$this->request->data('role', '0');
$user = $this->Users->patchEntity($user, $this->request->data);
if($this->Users->save($user)) {
$this->Flash->success('You are registered and can login');
return $this->redirect(['action' => 'login']);
} else {
$this->Flash->error('You are not registered');
}
}
$this->set(compact('user'));
$this->set('_serialize', ['user']);
}
When the user is registered I cant login (And I dont know why), but if I will login on other user and I'm changing the password for old user -> old user can log in.
I dont know where is the cause of issue.
Login:
//Login
public function login() {
if($this->request->is('post')) {
$user = $this->Auth->identify();
//dump($user);
//die();
if($user) {
if($user['status'] == '1') {
$this->Auth->setUser($user);
return $this->redirect(['controller' => 'tasks']);
}elseif($user['status'] == '0') {
$this->Flash->error('You are not authorized to Log In. Please contact with Admin of Application');
}
} else {
//Bad Login
$this->Flash->error('Incorrect Login or Password');
}
}
}
The interesting thing is that when I'm logging and i wrote
dump($user);
die();
I'm receiving "false"...
Login.ctp:
<div class="index large-4 medium-4 large-offset-4 medium-offset-4 columns">
<div class="panel">
<center><?= $this->HTML->image('small_logo.png'); ?></center>
<?= $this->Form->create(); ?>
<?= $this->Form->input('email'); ?>
<?= $this->Form->input('password'); ?>
<center><?= $this->Form->submit('Log In', array('class' => 'button')); ?></center>
<?= $this->Form->end(); ?>
</div>
I think the issue is related with 'DefaultHasherPassword' but i dont know where is the issue and how it should be resolved. Please help.
Its like new user cant login, but when the user is modified (password changed) - he can log in.
You may be forgot to add field username as email (not sure because you didn't share your code)
$this->loadComponent('Auth', [
'authenticate' => [
'Form' => [
'fields' => [
'username' => 'email', //email consider as username
'password' => 'password'
]
]
],
'loginAction' => [
'controller' => 'Users',
'action' => 'login'
]
]);
Hello Everyone i'm trying to login after i have successfully add user data into database, but login is not working,I'm new to cakephp.Please Help me out.
here is the code
appcontroller:
class AppController extends Controller {
public $components = array(
'DebugKit.Toolbar' ,'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'users', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login')
)
);}
UsersController:
public function login(){
if ($this->request->is('Post')) {
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirectUrl());
}//$this->Flash->error(__('Invalid username or password, try again'));
}
}
login.ctp:
<?php
echo $this->Form->create('User');
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->end('login');
?>
Add password hashing to your User model
User.php
App::uses('AppModel', 'Model');
class User extends AppModel {
public function beforeSave($options = array()) {
if(isset($this->data['User']['password'])) {
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
}
}
}
after that truncate your user table and save fresh user and then check again the login.
In version 2.2.1 I could validate a form using rules and custom messages like below. But somehow the password rule isn't working as of version 2.3. Any help what I might be doing wrong here?
Model:
class User extends AppModel {
public $validate = array(
'password' => array(
'rule' => array ('between', 5, 10 ),
'message' => 'Password must between 5 and 10 characters long'
)
);
public function beforeSave($options = array()) {
$this->data['User']['password'] = Security::hash($this->data['User']['password'], 'sha1', true);
return true;
}
}
View:
<?php
echo $this->Form->create();
echo $this->Form->input('firstname', array('label' => 'First name'));
echo $this->Form->input('lastname', array('label' => 'Last name'));
echo $this->Form->input('adminrole', array('type' => 'checkbox', 'label' => 'Is admin?<br /><br />'));
echo $this->Form->input('email', array('label' => 'E-mail address'));
echo $this->Form->input('password', array('label' => 'Password'));
echo $this->Form->input('picturethumb', array('type' => 'file', 'label' => 'Profile picture'));
echo $this->Form->end('Save');
?>
Please bare in mind that this exact same code validates correctly in 2.2.1
Controller:
class UsersController extends AppController {
public function index() {
$users = $this->User->find('all');
$this->set('users', $users);
}
public function add() {
if ($this->request->is('post')) {
$this->User->save($this->request->data);
$this->redirect('/users');
}
}
}
Try this-
public function add() {
if ($this->request->is('post')) {
$this->User->create();
if($this->User->save($this->request->data)){
$this->redirect('/users');
}else{
$this->Session->setFlash('Opps... Something is wrong');
}
}
}
I don't work with cake sometime, but I remember had this problem before. The problem is, the cakephp will create a hash of password, so when Model get password is already big. What I did in time was make another validate, like password_tmp and use it like field and create the hash by myself in controller for the real field password.
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');
}
I am trying to finish this website in cake php that was previously in regular php, but as newbie in the cakephp world.. I have found some difficulties such as these.
1) .When I click on login, it transfers me to another page although i have specified no redirects in app controller except when there is a registration. The login is at the top and its viewable through out all the pages, but if i click login, it redirects me to the login page (which i do not want).
2.) After I login, it brings in the session with the user name saying welcome 'username' but then if I go to another page, it seems like it forgets the session and brings back the inputs for the login form at the top of the page.
Here is my code
app_controller
<?php
class AppController extends Controller {
var $helpers = array('Html', 'Form', 'Javascript', 'Session');
var $components = array('Auth', 'Session');
function beforeFilter() {
$this->Auth->allow('add','get_categories','get_home', 'get_others', 'pages');
$this->Auth->autoRedirect = false;
}
}
?>
UsersController
<?php
class UsersController extends AppController {
var $uses = array("User");
var $components = array('Auth', 'Session');
function index()
{
$this->set('users', $this->User->find('all'));
$this->layout = 'master_layout';
}
function add() {
if (!empty($this->data)) {
//pass is hashed already
//->data['User']['password'] = $this->Auth->password($this->data['User']['password']);
if ($this->User->save($this->data)) {
$this->Session->setFlash('Your were registered!.');
$this->redirect(array('action' => 'get_home'));
}
}
$this->layout = 'master_layout';
}
//IF THE DATABASE IS SET UP CORRECTLY CAKE AUTHENTICATES AUTOMATICALLY NO
//LOGIC IS NEEDED FOR LOGIN http://book.cakephp.org/view/1250/Authentication
function login() {
$this->layout = 'master_layout';
if ($this->data) {
if ($this->Auth->login($this->data)) {
// Retrieve user data
$results = $this->User->find(array('User.username' => $this->data['User']['username']), array('User.active'), null, false);
$this->redirect(array('controller' => 'users', 'action' => 'login'));
}
}
$this->data['User']['password'] = '';
}
function logout() {
$this->redirect($this->Auth->logout());
}
}
?>
elements/loginform.ctp
<?php
if ($this->Session->read('Auth.User.username')):?>
<?php
echo "Welcome".' ' ;
echo $this->Session->read('Auth.User.username');
echo " ";
echo $html->link('logout', array('action'=>'logout'));
?>
<?php else : ?>
<div class="types form">
<?php echo $form->create('User', array('controller' => 'Users','action' => 'login')); ?>
<?php echo $form->input('username', array('label' => 'username')); ?>
<?php echo $form->input('password',array('type'=>'password', 'label' => 'password')) ?>
<?php echo $form->submit('Submit'); ?>
</div>
<?php endif; ?>
UPDATE
I added the following to the app_controller
<?php
class AppController extends Controller {
var $helpers = array('Html', 'Form', 'Javascript', 'Session');
var $components = array('Auth', 'Session');
function beforeFilter() {
//new addition
$this->set('userData', $this->Session->read());
$this->Auth->allow('add','get_categories','get_home', 'get_others', 'pages', '*');
$this->Auth->autoRedirect = false;
}
}
?>
WHEN I LOGIN I GET THIS ARRAY
Array ( [Config] => Array
( [userAgent] => 8f12200c2d48fa7955465842befe1c9e
[time] => 1323562284 [timeout] => 10 )
[Auth] => Array (
[User] => Array (
[id] => 63
[user_role] => 2 [
[user_fname] => test
[user_lname] => test
[user_email] => test#test.com
[user_phone] => 677-988-7777
[user_cellphone] => 555-456-9999
[user_address1] => 1st Avenue
[user_address2] =>
[user_city] => Citiland FL
[user_zip] => 55555
[username] => admin2 ) ) )
BUT WHEN I NAVIGATE TO A NEW PAGE
Array ( [Config] => Array (
[userAgent] => 8f12200c2d48fa7955465842befe1c9e
[time] => 1323562591 [timeout] => 10 ) )
ADDED PRINT_R TO elements/loginform TO SEE THE VARIABLE CONTENTS ACROSS ALL PAGES
<?php
print_r($userData);
if ($this->Session->read('Auth.User.username')):?>
<?php
echo "Welcome".' ' ;
echo $this->Session->read('Auth.User.username');
echo " ";
echo $html->link('logout', array('action'=>'logout'));
?>
<?php else : ?>
<div class="types form">
<?php echo $form->create('User', array('controller' => 'Users','action' => 'login')); ?>
<?php echo $form->input('username', array('label' => 'username')); ?>
<?php echo $form->input('password',array('type'=>'password', 'label' => 'password')) ?>
<?php echo $form->submit('Submit'); ?>
</div>
<?php endif; ?>
1) This is because in your UsersController you have a redirect after the user is logged in.
Your login function should instead read:
function login() {
$this->layout = 'master_layout';
if ($this->data) {
if ($this->Auth->login($this->data)) {
// Retrieve user data
$results = $this->User->find(array('User.username' => $this->data['User']['username']), array('User.active'), null, false);
/*This is the offending line, I've commented it out, but you could have it redirect somewhere else (it might be a good idea to redirect to the index action, for example, or just delete it:*/
//$this->redirect(array('controller' => 'users', 'action' => 'login'));
}
}
$this->data['User']['password'] = '';
}
As for 2), I believe it may be because you are not setting the data afterwards, so that while it exists in a tmp directory on the server (using the Session component) it is not actually being passed along to the view. So basically I think it's because you can't call Session methods in the view. Even if I'm not entirely correct about that, what I'm suggesting to do should work: Instead of calling session methods in the view, call them in the controller, set them in a variable for the view to access using $this->set();, then test against that variable in the view.
If you need to do this for ton of views and actions, you could consider adding something like this to your controller or even your app controller:
function beforeFilter() {
// Get session data for appllication use
$this->appuserstuff = $this->Session->read();
}
function beforeRender() {
// Make app variables available to view
$this->set('userData', $this->appuserstuff);
}
Alternatively, if you just need this in a couple actions, you could just set the user data in those actions with a:
$this->set('userData', $this->Session->read());
Now I'd recommend that you do a <?php debug($userData); ?> in one of your views so you can see how the data is structured in the array when it is set, so that you can user or test conditionals against. Finally, you could replace the direct calls to Session in your view with instead checks against the array of data:
Please note that I'm not sure how your specific array is structured so do a debug as recommended above and plug in your own keys for it to work:
<?php
if (!empty($userData['User'])):?>
<?php
echo "Welcome".' ' ;
echo $userData['User']['username'];
echo " ";
echo $html->link('logout', array('action'=>'logout'));
?>
<?php else : ?>
<div class="types form">
<?php echo $form->create('User', array('controller' => 'Users','action' => 'login')); ?>
<?php echo $form->input('username', array('label' => 'username')); ?>
<?php echo $form->input('password',array('type'=>'password', 'label' => 'password')) ?>
<?php echo $form->submit('Submit'); ?>
</div>
<?php endif; ?>