how to make confirm password validation cakephp with hashing it - php

I'm using cakephp 2.xx, I want to hashing password with sha256 before it going to database,
before it I wanna make validation value password in my form input, validation which check password input and re-confirm password is match, if In my controller, when form catch validation, the password automatically hash
if ($this->request->data['Driver']['password'] != $this->request->data['Driver']['confirm_password']) {
$this->request->data['Driver']['password'] = hash('sha256',$this->request->data['Driver']['password']);
}
necessarily, the password hash when form no catch validate at all, so how can I make validation in my model ?
Thanks In Advance.

In your model (Driver.php)
Validation
<?php
public $validate = array(
'password' => array(
'notempty' => array(
'rule' => array('notempty'),
),
'password_confirm'=>array(
'rule'=>array('password_confirm'),
'message'=>'Password Confirmation must match Password',
),
),
);
?>
Custom validation rule
<?php
public function password_confirm(){
if ($this->data['Driver']['password'] !== $this->data['Driver']['password_confirmation']){
return false;
}
return true;
}
?>
Hashing,but I think that better to choose AuthComponent
<?php
public function beforeSave($options = array()) {
$this->data['Driver']['password'] = hash('sha256',$this->data['Driver']['password']);
return true;
}
?>
It's overall description and you probably would need to modify some parts of it

Related

Updating user with or without password - CakePHP

I try to find a good and clean way to deal with an admin panel "edit user" in cakePHP v.2.7.
To be clear : I want to be able to edit my user with or without overwriting their password, but the cakePHP validator tool don't let me do what I want...
I've already take a look at CakePHP: Edit Users without changing password and Updating user email and password with CakePHP but it seem really dirty :
the first one don't apply the rules onUpdate
the second display the hash (just no... u_u")
There is no other way to do it ? (with as few line as possible)
TL;DR :
View
// add in your view `app/View/Users/edit.ctp`
// a 'fake' field you'll only use on the controller
echo $this->Form->input('new_password');
Controller
// add in your controller `app/Model/User.php#edit()`
// if we have a new password, create key `password` in data
if(!empty($new_password = $this->request->data['User']['new_password']))
$this->request->data['User']['password'] = $new_password;
else // else, we remove the rules on password
$this->User->validator()->remove('password');
Ok, I finally get what I want, here is my code :
On your app/View/Users/edit.ctp you add a field to your form (a custom one, don't add it to your DB)
<?php
// app/View/Users/edit.ctp
echo $this->Form->create('User');
// your other fields
// a 'fake' field you'll only use on the controller
echo $this->Form->input('new_password');
Don't change your app/Model/User.php ; here is mine :
<?php
// app/Model/User.php
App::uses('AuthComponent', 'Controller/Component');
class User extends AppModel {
public $validate = array(
// [...] other rules
'password' => array(
'passwordLength'=>array(
'rule' => array('minLength', 8),
'message' => 'Too short...',
),
'passwordNotBlank'=>array(
'rule' => 'notBlank',
'required' => true,
'allowEmpty' => false,
'message' => 'A password is required',
),
),
);
public function beforeSave($options = array()) {
if (!empty($pwd = $this->data[$this->alias]['password']))
$this->data[$this->alias]['password'] = AuthComponent::password($pwd);
return true;
}
}
And on your app/Controller/UsersController.php you use this :
<?php
public function edit($id = null) {
$this->User->id = $id;
if (!$this->User->exists())
throw new NotFoundException(__('Invalid user'));
if ($this->request->is('post') || $this->request->is('put')) {
// IMPORTANT >>>>>>>>>>>
// if we have a new password, create key `password` in data
if(!empty($new_password = $this->request->data['User']['new_password']))
$this->request->data['User']['password'] = $new_password;
else // else, we remove the rules on password
$this->User->validator()->remove('password');
// <<<<<<<<<<<<<<<<<<<<<
// then we try to save
if ($this->User->save($this->request->data)) {
$this->Flash->success(__('The user has been updated'));
$this->redirect(array('action' => 'index'));
}
else
$this->Flash->warning(__('The user could not be updated.'));
}
else {
$this->request->data = $this->User->read(null, $id);
unset($this->request->data['User']['password']);
}
}
With the 4 important lines, you are now able to set a new password if needed or disable the validation on the password.
I used this for reference
http://book.cakephp.org/2.0/en/models/data-validation.html#removing-rules-from-the-set

CakePHP 3 - Compare passwords

I have two field "password" (This field is in the database) and confirm_password (This field is not in the database)
Well, I need to compare if password == confirm_password.. but I'm not knowing create a custom validation to "confirm_password"... Would need to have this field in the database?
How do I do?
Generally you can access all data in a custom validation rule via the $context argument, where it's stored in the data key, ie $context['data']['confirm_password'], which you could then compare to the current fields value.
$validator->add('password', 'passwordsEqual', [
'rule' => function ($value, $context) {
return
isset($context['data']['confirm_password']) &&
$context['data']['confirm_password'] === $value;
}
]);
That being said, recently a compareWith validation rule was introduced which does exactly that.
https://github.com/cakephp/cakephp/pull/5813
$validator->add('password', [
'compare' => [
'rule' => ['compareWith', 'confirm_password']
]
]);
Now there has a method call sameAs in validator class, for version 3.2 or grater.
$validator -> sameAs('password_match','password','Passwords not equal.');
see API
I know it's late answer but will help to other.
// Your password hash value (get from database )
$hash = '$2y$10$MC84b2abTpj3TgHbpcTh2OYW5sb2j7YHg.Rj/DWiUBKYRJ5./NaRi';
$plain_text = '123456'; // get from form and do not make hash. just use what user entred.
if (password_verify($plain_text, $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
OR
$hasher = new DefaultPasswordHasher();
$check = $hasher->check($plain_text,$hash); // it will return true/false

CodeIgniter form validation, show errors in order

Lets say I have a login form and it has fields username and password. Both of the fields are required to be filled in and when you submit the form it has two different lines for them.
Username field is required.
Password field is required.
What I want to do is to show only the username field errors and when they don't have any errors with username field, it will show the password field errors.
How would this be done?
Also, I remember there is a way to show errors only regarding a field, what was the snippet for it?
I suggest using a custom callback function tied to just one input, that checks both inputs and conditionally sets the desired message.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class YourController extends CI_Controller {
public function save()
{
//.... Your controller method called on submit
$this->load->library('form_validation');
// Build validation rules array
$validation_rules = array(
array(
'field' => 'username',
'label' => 'Username',
'rules' => 'trim|xss_clean|callback_required_inputs'
),
array(
'field' => 'password',
'label' => 'Password',
'rules' => 'trim|xss_clean'
)
);
$this->form_validation->set_rules($validation_rules);
$valid = $this->form_validation->run();
// Handle $valid success (true) or failure (false)
if($valid)
{
//
}
else
{
//
}
}
public function required_inputs()
{
if( ! $this->input->post('username'))
{
$this->form_validation->set_message('required_inputs', 'The Username field is required');
return FALSE;
}
else if ($this->input->post('username') AND ! $this->input->post('password'))
{
$this->form_validation->set_message('required_inputs', 'The Password field is required');
return FALSE;
}
return TRUE;
}
}

Cakephp Auth hashPasswords rewrite Problems

I've been using this tutorial to rewrite my login/logout functionality to handle authentication and matching passwords in the model.
It now adds the user perfectly, but upon login the username/password fields are rejected. It seems the login function is looking for a differently hashed password than my new hashPasswords() function is storing. Any suggestions on what the problem could be?
It's a fairly standard setup. Thanks for any help!
Pertinent Sections of code:
User Model:
var $validate = array(
'password' => array(
'The Password must be filled' =>array(
'rule' => 'notEmpty',
'message' => 'Please supply a valid password.'
),
'The Password must be between 5 and 15 characters' => array(
'rule' => array('between', 5, 15),
'message' => 'The password must be between 5 and 15 characters.'
),
'The passwords do not match' => array(
'rule' => 'matchPasswords',
'message' => 'The passwords do not match.'
)
),
function hashPasswords($data) {
if (isset($this->data['User']['password'])) {
$this->data['User']['password'] = Security::hash($this->data['User']['password'], NULL, TRUE);
return $data;
}
return $data;
}
function beforeSave() {
$this->hashPasswords(NULL, TRUE);
return TRUE;
}
Users Controller:
function beforeFilter() {
parent::beforeFilter();
if ($this->action == 'add' || $this->action == 'edit' ) {
$this->Auth->authenticate = $this->User;
}
}
function add() {
if (!empty($this->data)) {
if ($this->User->save($this->data)) {
$this->Session->setFlash('Your Account Has Been Created.');
$this->redirect(array('action' => 'homepage'));
}
}
}
function login() {
}
I haven't seen the video, but -
When $this->data['User'] has a 'username' and 'password' array, and is used to save a user - cake actually hashes the password. What may potentially be happening is your hashed password being hashed again - check out the cake documentation on hashPassword
As far as password matching goes - it is actually far easier to do this on the client side where they aren't hashed (lots of Jquery functions out there that validate forms). You can even go as far as writing a simple:
if($this->data['User']['password'] != $this->data['User']['password_conf']{
$this->Session->setFlash('Passwords do not match');
} else {
//save user etc
}
If you want validate in the model, then certainly write a custom validation rule - but again the password will be hashed for you - you only need to compare the non-hashed versions and see if they match, returning true if they do.
Also - everyone has completely different ways of authenticating users - first and foremost read the documentation - there's an excellent tutorial for a simple Authenticated / ACL application which takes about 30 mins to go through and should be anyones starting point.

CakePHP: Clearing password field on failed submission

Greetings,
I am setting up a pretty standard registration form with password field.
The problem is, after a failed submission (due to empty field, incorrect format etc), the controller reloads the registration page, but with the password field containing the hashed value of the previously entered password. How do I make it empty after each failed submission?
View:
echo $form->password('Vendor.password', array('class' => 'text-input'));
Controller:
Security::setHash('sha1');
$this->Auth->sessionKey = 'Member';
$this->Auth->fields = array(
'username' => 'email',
'password' => 'password'
);
Help is very much appreciated, thanks!
You may run into another problem down the road with cakePHP password validation.
The problem is that cake hashes passwords first, then does validation, which can cause the input to fail even if it is valid according to your rules. This is why the password is returned to the input field hashed instead of normal.
to fix this, instead of using the special field name 'password', use a different name like 'tmp_pass'. This way, cakePHP Auth won't automatically hash the field.
Here's a sample form
echo $form->create('Vendor', array('action' => 'register'));
echo $form->input('email');
echo $form->input( 'tmp_pass', array( 'label' => 'Password','type'=>'password' ));
echo $form->end('Register');
In your Vendor model, don't assign validation rules to 'password' instead assign these rules to 'tmp_pass', for example
var $validate = array('email' => 'email', 'password' => ... password rules... );
becomes
var $validate = array('email' => 'email', 'tmp_pass' => ... password rules... );
Finally, in your Vendor model, implement beforeSave().
First, see if the data validates ('tmp_pass' will be validated against your rules).
If successful, manually hash tmp_pass and put it in $this->data['Vendor']['password'] then return true. If unsuccessful, return false.
function beforeSave() {
if($this->validates()){
$this->data['Vendor']['password'] = sha1(Configure::read('Security.salt') . $this->data['User']['tmp_pass']);
return true;
}
else
return false;
}
this?
password('Vendor.password', array('class' => 'text-input','value'=>''))
In your controller:
function beforeRender() {
parent::beforeRender();
$this->data['Vendor']['password'] = '';
}

Categories