I try to make hashing while changing password correctly , but i cant, always after changing password, it's hashing twice or i don;t know. Please tell me what am i doing wrong.
class User extends AppModel
{
var $validate = array(
'name' => array(
'length' => array(
'rule' => array('minLength', 5),
'message' => 'Please enter your full name (more than 5 chars)',
'required' => true,
),
),
'username' => array(
'length' => array(
'rule' => array('minLength', 5),
'message' => 'Must be more than 5 characters',
'required' => true,
),
'alphanum' => array(
'rule' => 'alphanumeric',
'message' => 'May only contain letters and numbers',
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'Already taken',
),
),
'email' => array(
'email' => array(
'rule' => 'email',
'message' => 'Must be a valid email address',
),
'unique' => array(
'rule' => 'isUnique',
'message' => 'Already taken',
),
),
'password' => array(
'empty' => array(
'rule' => 'notEmpty',
'message' => 'Must not be blank',
'required' => true,
),
),
'password_confirm' => array(
'required' => array(
'rule' => array('equalToField', 'password', true),
'message' => 'The password you entered does not match',
),
'length' => array(
'rule' => array('between', 6, 20),
'message' => 'Use between 6 and 20 characters',
),
'empty' => array(
'rule' => 'notEmpty',
'message' => 'Must not be blank',
),
),
);
function equalToField($array, $field) {
return strcmp($this->data[$this->alias][key($array)], $this->data[$this->alias][$field]) == 0;
}
var $validateChangePassword = array(
'_import' => array('password', 'password_confirm'),
'password_old' => array(
'correct' => array(
'rule' => 'password_old',
'message' => 'Does not match',
'required' => true,
),
'empty' => array(
'rule' => 'notEmpty',
'message' => 'Must not be blank',
),
),
);
function useValidationRules($key)
{
$variable = 'validate' . $key;
$rules = $this->$variable;
if (isset($rules['_import'])) {
foreach ($rules['_import'] as $key) {
$rules[$key] = $this->validate[$key];
}
unset($rules['_import']);
}
$this->validate = $rules;
}
function password_old($data)
{
$password = $this->field('password',
array('User.id' => $this->id));
return $password ===
Security::hash($data['password_old'], null, true);
}
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;
}
And then my controller:
class UsersController extends AppController
{
var $components = array('Email');
/**
* Account details page (change password)
*/
function account()
{
// Set User's ID in model which is needed for validation
$this->User->id = $this->Auth->user('id');
// Load the user (avoid populating $this->data)
$current_user = $this->User->findById($this->User->id);
$this->set('current_user', $current_user);
$this->User->useValidationRules('ChangePassword');
$this->User->validate['password_confirm']['compare']['rule'] =
array('equalToField', 'password', false);
$this->User->set($this->data);
if (!empty($this->data) && $this->User->validates()) {
$password = $this->Auth->password($this->data['User']['password']);
$this->User->saveField('password', $password);
$this->Session->setFlash('Your password has been updated');
$this->redirect(array('action' => 'account'));
}
}
/**
* Registration page for new users
*/
// function register()
// {
// if (!empty($this->data)) {
// $this->User->create();
// if ($this->User->save($this->data)) {
// $this->Session->setFlash(__('Your account has been created.', true));
// $this->redirect('/');
// } else {
// $this->Session->setFlash(__('Your account could not be created.', true));
// }
// }
// }
public function register(){
if($this->request->is('post')){
$this->User->create();
if($this->User->save($this->request->data)){
$this->Session->setFlash(__('Użytkownik został zapisany', 'success'));
$this->redirect(array('controller'=>'ads', 'action'=>'index'));
} else {
$this->Session->setFlash(__('Błąd zapisu'), 'error');
}
}
}
/**
* Log a user out
*/
function logout()
{
return $this->redirect($this->Auth->logout());
}
/**
* Ran directly after the Auth component has executed
*/
function login()
{
// Check for a successful login
if($this->request->is('post')){
if($this->Auth->login()){
$this->User->id = $this->Auth->user('id'); // zapisuje date logowania
$this->User->saveField('lastlogin', date(DATE_ATOM)); // zapisuje date logowania
$this->redirect($this->Auth->redirect());
} else {
$this->Session->setFlash(__('Nieprawidłowy login lub hasło'), 'error');
}
}
}
and the view:
echo $this->Form->create(array('action' => 'account'));
echo $this->Form->input('password_old', array('label' => 'Old password', 'type' => 'password', 'autocomplete' => 'off'));
echo $this->Form->input('password_confirm', array('label' => 'New password', 'type' => 'password', 'autocomplete' => 'off'));
echo $this->Form->input('password', array('label' => 'Re-enter new password', 'type' => 'password', 'autocomplete' => 'off'));
echo $this->Form->end('Update Password');
Change this line in account function in UsersController from
$password = $this->Auth->password($this->data['User']['password']);
to
$password = $this->data['User']['password'];
$this->Auth->password() do the same function as AuthComponent::password() in model.
So your password was hashing twice.
Related
I started using CakePHP 3.6 and I am having trouble to create the authentication login. The new auth function $this->Auth->identify() always returns false.
My code:
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler', [
'enableBeforeRedirect' => false,
]);
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authorize' => ['Controller'],
'loginRedirect' => [
'controller' => 'Users',
'action' => 'index'
],
'logoutRedirect' => [
'controller' => 'Users',
'action' => 'login',
'home'
],
Here is where I set the fields:
'authenticate' => [
'Form' => [
'fields' => ['username' => 'username', 'password' => 'password']
]
]
]);
/*
* Enable the following components for recommended CakePHP security settings.
* see https://book.cakephp.org/3.0/en/controllers/components/security.html
*/
//$this->loadComponent('Security');
//$this->loadComponent('Csrf');
}
class UsersController extends AppController
{
// Other methods..
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow(['logout']);
}
public function login()
{
if ($this->request->is('post')) {
This always returns false but why?
$user = $this->Auth->identify();
debug($this->request);
debug($user);
die;
if ($user) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
}
$this->Flash->error(__('Invalid username or password, try again'));
}
}
public function logout()
{
return $this->redirect($this->Auth->logout());
}
}
class User extends AppModel {
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'
)
),
'email' => array(
'email' => array(
'rule' => array('email', true),
'message' => 'Please supply a valid email address.'
),
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A email is required'
)
),
'role' => array(
'valid' => array(
'rule' => array('inList', array('admin')),
'message' => 'Please enter a valid role',
'allowEmpty' => false
)
)
);
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$passwordHasher = new SimplePasswordHasher();
$this->data[$this->alias]['password'] = $passwordHasher->hash(
$this->data[$this->alias]['password']
);
}
return true;
}
}
I followed the tutorials on the cakephp website with zero luck. Help!
Make sure that you test with a hashed password because the Auth component is expecting it to be hashed so this was my bad.
I am trying to add validation on change password function but it doesn't work.
I have added
->add('repeat_password', [
'equalToPassword' => [
'rule' => function ($value, $context) {
return $value === $context['data']['new_password'];
},
'message' => __("Your password confirm must match with your password.")
]
]);
to Users model
and in my controller
$user = $this->Users->get($this->_User['user_id']);
if ($this->request->is(['patch', 'post', 'put'])) {
$user = $this->Users->createEntity($user, ['password' => $this->request->data['repeat_password']]);
// $verify = (new DefaultPasswordHasher)->check($this->request->data['old_password'], $user->password);
// debug($verify);
//if ($verify) {
if ($this->Users->save($user)) {
$this->Flash->success('The password has been changed');
$this->redirect(['action' => 'index']);
} else {
$this->Flash->error('Password could not be issued');
}
}
// else {
// $this->Flash->error('Password Do not match');
// }
// }
}
It saves data without validating. What is the solution ?
Without having checked your code thoroughly, my first thought is that CakePHP 3 already provides the built-in validator compareWith for this purpose.
Try setting the validation rules as follows:
$validator->add('repeat_password', [
'compareWith' => [
'rule' => ['compareWith', 'new_password'],
'message' => __("Your password confirm must match with your password.")
]
]);
Also, check that both new_password and repeat_password are set to true in the $_accessible array.
public $validate = array(
'password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A password is required'
),
'min_length' => array(
'rule' => array('minLength', '6'),
'message' => 'Password must have a mimimum of 6 characters'
)
),
'password_confirm' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'Please confirm your password'
),
'equaltofield' => array(
'rule' => array('equaltofield','password'),
'message' => 'Both passwords must match.'
)
),
)
please write code in your model more detail please check below link
http://miftyisbored.com/a-complete-login-and-authentication-application-tutorial-for-cakephp-2-3/
I have been trying to get cakephp 2.6.3 auth component for my site to work for a week now.
The problem am facing is that when ever I enter any bogus user ID/password combination, the login function returns true. i have read all is there to read and watched tutorials but I can't seem to get this to work.
I am new to using Cake, your help will be greatly appreciated. Thanks in advance.
Below is my appController.
class AppController extends Controller {
public $components = array(
'DebugKit.Toolbar',
'Session',
'Auth' => array(
'loginAction' => array('controller' => 'users', 'action' => 'login'),
'loginRedirect' => array('controller' => 'users', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'users', 'action' => 'login'),
'Authenticate' => array(
'Form' => array(
'fields' => array('username' => 'student_id', 'password' => 'password')
)
)
)
);
public function isAuthorized($user){
return true;
}
public function beforeFilter(){
$this->Auth->allow('login');
}
}
UsersController:
public function login(){
if($this->request->is('post')){
if($this->Auth->login()){
$this->redirect($this->Auth->redirectUrl());
}
else{
$this->Session->setFlash('Invalid User ID or password');
}
}
}
User's model:
class User extends AppModel{
public $name = 'User';
public $validate = array(
'student_id' => array(
'Please enter your User ID' => array(
'rule' => 'notEmpty',
'message' => 'Please enter your User ID.'
)
),
'first_name' => array(
'Enter First Name' => array(
'rule' => 'notEmpty',
'Message' => 'Please enter first name.')),
'last_name' => array(
'Enter Last Name' => array(
'rule' => 'notEmpty',
'Message' => 'Please enter last name.')),
'email' => array(
'Valid email' => array(
'rule' => array ('email'),
'Message' => 'Please enter a valid email.')),
'password' => array(
'Not empty' => array(
'rule' => 'notEmpty',
'Message' => 'Please enter your password.'),
'Match passwords' => array(
'rule' => 'matchPasswords',
'Message' => 'Your passwords donot match')),
'password_confirmation' => array(
'Not empty' => array(
'rule' => 'notEmpty',
'Message' => 'Please confirm your password.'))
);
public function matchPasswords($data){
if($data['password'] == $this->data['User']['password_confirmation']){
return true;
}
$this->invalidate('password_confirmation', 'Your passwords do not match');
return false;
}
public function beforeSave($options = array()){
if(isset($this->data['User']['password'])){
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
}
return true;
}
}
Good answer here :
Cake PHP 2.4.x. AuthComponent login() always return true;
Also read this :
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#identifying-users-and-logging-them-in
Get rid of $this->Auth->allow('login'); from your beforeFilter() method.
This seemed to be working perfectly, I added a checkbox to my form so the user can decide whether to change the password or not. In the add user action the validation works fine and won't save the user if there are any errors, but with my edit user action it will still save them when both password fields are blank, but still validate them properly if there's any data in either password input. Here's my model:
class User extends AppModel {
var $name = 'User';
var $displayField = 'name';
var $validate = array(
'username' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'User must have a username to login with',
),
),
'password' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'User must have a password',
),
'alphanumeric' => array(
'rule' => array('alphanumeric'),
'required' => true,
'message' => 'User must have a password'
),
'minlength' => array(
'rule' => array('minlength', 6),
'message' => 'Password must be at least 6 characters',
),
'confirmPassword' => array(
'rule' => array('confirmPassword', 'password'),
'message' => 'Passwords do not match'
),
),
'password_confirm' => array(
'notempty' => array(
'rule' => array('notempty'),
'message' => 'User must have a password',
),
'alphanumeric' => array(
'rule' => array('alphanumeric'),
'required' => true,
'message' => 'User must have a password'
),
'minlength' => array(
'rule' => array('minlength', 6),
'message' => 'Password must be at least 6 characters',
),
),
);
function confirmPassword($data) {
return ($data['password'] === Security::hash(Configure::read('Security.salt').$this->data['User']['password_confirm']));
}
And here's my edit user action:
function admin_edit($id = null) {
$this->set('title_for_layout', 'Users / Editing User');
if (!$id && empty($this->data)) {
$this->Session->setFlash(__('Invalid user specified', true), 'flash_error');
$this->redirect(array('action' => 'index'));
}
if (!empty($this->data)) {
$redirect = array('action' => 'index');
if ($this->data['User']['edit_password'] == 1) {
$fields = array('username', 'confirm_password', 'password', 'name');
if ($this->data['User']['id'] == $this->Auth->user('id')) {
$redirect['action'] = 'logout';
}
} else {
$fields = array('username', 'name');
}
if ($this->User->save($this->data, true, $fields)) {
$this->Session->setFlash(__(sprintf('The user <i>%s</i> was saved successfully.', $this->data['User']['username']), true), 'flash_success');
$this->redirect($redirect);
} else {
$this->Session->setFlash(__('There were errors when trying to save the user', true), 'flash_error');
}
}
if (empty($this->data)) {
$this->data = $this->User->read(null, $id);
$this->data['User']['password'] = '';
$this->data['User']['edit_password'] = 0;
}
}
Sorry in advance as this is only a half-answer, but should get you moving in the right direction.
The Auth component will automatically hash the password field if the username field is also present in the submitted data
So you have set up your data to either anticipate this.. or avoid it.
This method will come in handy too.
http://book.cakephp.org/view/1259/hashPasswords
I'm working on the signup process and want to check if the two passwords (password + re-entered password) are equal. These are my validation rules in the User Model:
var $validate = array(
'username' => array(
'notEmpty' => array(
'rule' => array('minLength', 5),
'required' => true,
'allowEmpty' => false,
'message' => 'User name has to be at least 5 characters long'
),
array(
'rule' => 'isUnique',
'message' => 'User name taken. Use another'
)
),
'password' => array(
'notEmpty' => array(
'rule' => array('minLength', 6),
'required' => true,
'allowEmpty' => false,
'message' => 'Password has to be at least 6 characters long'
),
'password_similar' => array(
'rule' => 'checkPasswords',
'message' => 'Entered passwords does not match'
)
),
'email' => array(
'rule' => 'email',
'required' => true,
'allowEmpty' => false,
'message' => 'Please enter a valid email'
)
);
In the users_controller.php I have the checkPasswords function:
function checkPasswords($data) {
if($data['password'] == $this->data['User']['password2hashed'])
return true;
else
return false;
}
An my singup function looks like this:
function signup(){
if (!empty($this->data)) {
if(isset($this->data['User']['password2']))
$this->data['User']['password2hashed'] = $this->Auth->password($this->data['User']['password2']);
$this->User->create();
if ($this->User->save($this->data)) {
.
.
.
}
No matter what I do, the passwords do not match. Even if I change the checkPasswords function to this:
function checkPasswords($data) {
return true;
}
What could cause this behavior?
OMG I just realised that the checkPasswords Function is not supposed to be in the controller but in the model. Problem solved, I'm ashamed...