I am using CakePHP for my application, where I have a User model. This User has a password, which has a regex to validate.
The regex forces the user to use a password at least 6 characters long, containing at least 1 number and special char.
The validation looks like this:
'password' => array(
'ruleName' => array(
'rule' => array('custom', '/^.*(?=.{6,})(?=.*\d)(?=.*[a-zA-Z])(?=.*[##$%^&+=]).*$/i'),
'message' => 'Password not legit',
'allowEmpty' => true
)
)
When I want to edit my password, this validation works great. But when I want to edit the user (no option to change password there), the $this->User->save() fails.
If I debug my $this->User->validationErrors, the only thing shown is:
array(
'password' => '*****'
)
The password field is not set in my post data, so the validation should not happen at all.
When I comment this block of validation code, the user can be saved.
Anyone knows what I am doing wrong?
I solved it myself already. Before saving the User object, I already did a $this->User->Read(null, $userid) for other purposes.
This resulted in remembering the values of the read (including password) in the $this->User object.
Since the save method is called on the $this->User object, the password value is trying to get saved too. But since *** isn't valid according to the regex, the save fails.
Thanks for the help anyway!
Related
I've struggled with a problem for a while now. I want to use Laravel for my website BUT I can only use SHA256 as the password encryption because of some other limitations in our project.
Basicly my problem consists of a function within Laravel that is used to check if the userdata is correct (Checks if the user can login) does not work for me because of my difference in encryption (Atleast that's my theory)
Auth::attempt(['username' => $username, 'password' => $password]
This function always returns false, no matter if the password is correct and I assume it's because of the difference in encryption.
Anybody know if there's a fix for this?
Auth::attempt(['username' => $username, 'password' => SHA256($password)]);
Here SHA256($password) you can call the function as the same which used for encryption and check it.
In this case, SHA256 (dummy function) will hash the password you passed and match the value.
EDIT 1
Sample Code for registration
$users = User::create([
'name' => $name,
'email' => $email,
....
....
'password' => SHA256($password)
]);
//to login with the above creds
Auth::login($users);
Now while login you can use the same SHA256 function to encrypt the input password and check with your database.
I fixed this issue with the help of the above comments from Arun Code and Andrew.
For anyone else with this issue I suggest reading this
I was investigating CakePHP (2.3.4) Model::save method to insert new records and ran into a little snag:
//Two fields provided, email field intended to fail validation
$data = array('Member' => array(
'username' => 'hello',
'email' => 'world'
));
$this->Member->create();
var_dump($this->Member->save($data, true));
The above save() will return false and no data will be written to the database. However if I change the data to:
//One field provided, intended to pass validation
$data = array('Member' => array(
'username' => 'hello'
));
then save() will attempt to write a new record to database with a blank email field. I realize that skipping validation for unspecified fields might be a useful behavior during updates, but is there a CakePHP recommended way to handle partially empty data sets when creating new records? Thanks a lot.
Edit:
Thanks to Sam Delaney for the tip. In case anybody else gets stumped, this did the trick: CakePHP Data Validation: field 'required' key
This key accepts either a boolean, or create or update. Setting this key to true will make the field always required. While setting it to create or update will make the field required only for update or create operations. If ‘required’ is evaluated to true, the field must be present in the data array. For example, if the validation rule has been defined as follows:
I had originally baked the model and forgotten that required => true was left out of the validation rule. Setting it to true or 'create' would've avoided me blank records getting inserted due to gibberish data array.
IMHO what you've experienced is the desired behavior. Consider that you have the same two fields within a form and the user provides a value for only username. Both username and email field are submitted even though email is empty. Then on the server, you try to save the record only to find out that it has failed validation which you feedback to the user. On the other hand, perhaps in your system it is perfectly possible to create a user without requiring an email (for example root access account), CakePHP's validation implementation allows both of these scenarios.
If this flexibility isn't what you desire, just set the required attribute for your validation rule as true:
public $validate = array(
'email' => array(
'rule' => 'email',
'required' => true
)
);
This will satisfy your all or nothing requirement.
I'm quite new to Auth module, and i'm trying to get login working, after reading documentation and googling like crazy i have this simple piece of code...
Auth::instance()->login('test', 'test');
if (Auth::instance()->logged_in()){
$this->request->redirect('user/index/');
}else{
echo 'fail';
}
This always returns false, my registration script looks like this:
$model = ORM::factory('user');
$model->values(array(
'username' => 'admin',
'email' => 'adsmin#example.com',
'password' => 'test',
'password_confirm' => 'test',
));
$model->save();
It creates user just fine, also it sets role_id to 1 and 2 which means i have admins/login rights, but it keeps failing anyways, if i would use Auth::instance()->force_login($user); everything work's just fine, so i'm guessing problem could be with hashing, but i have no idea where.
You must set driver to 'orm' in config/auth.php
Did you store the plaintext password or the hashed password? I think the Auth module login function hashes the password. So maybe you should save the hashed password.
You could hash your password by using:
Auth::instance()->hash('your_password');
I'm writing this in PHP, but, generally speaking, what methods and properties would a user (registration?) class have? I know I can use MDB2 from PEAR for database abstraction, and one feature I can think of is making sure the username is valid.
$user->validateUserName($username, $regex);
Can anybody think of any more?
Thanks.
Edit:
Username validation would be a class of its own right (Validator class or something)?
Well, you should check if
Username is already in use
Password is strong enough
User's Mail address is valid
You also need methods to
create a new account
change User's data
delete an existing account?
allow Users to recover forgotten pws
There shouldn't be a such class at all. Registration is a whole process of receiving data, validating that data and finally, processing validated data if validation succeed. In other words: registration is that part of code which uses some object to solve a given problem.
What will you need?
An object that represents a single user.
An object that takes User object and saves it.
Some validation mechanism (it will use at least several objects).
Let's design an interface. How will we use the code we're going to write?
try {
$validator = new Validator($_POST);
$validator->addRules(array(
'username' => new LengthValidator(array('min' => 3, 'max' => 15)),
'password' => array(
new LengthValidator(array('min' => 6))
new RegexpValidator(array('pattern' => '#...#'))
),
'email' => array(
new EmailValidator(),
new UniqueValidator(....)
)
));
$data = $validator->validate();
$userService = new UserService($databaseHandler, $someOtherArguments);
$user = new User();
$user->setUsername($data['username']);
$user->setPassword($data['password']);
$user->setEmail($data['email']);
$user->setFirstname($data['firstname']);
$user->setLastname($data['lastname']);
$userService->save($user);
} catch (ValidationException $ve) {
// validation failed
}
That's of course only an example - it can be designed totally different way.
ValidForm, it's a great class structured to handle your forms both client/server-sided. However, no MySQL is passed through the form.
How do I run validation checks on a password field in CakePHP, seeing that the password is hashed before I get a chance to run any checks on it?
If you only have a single password field in your form, you will need to create a custom hash function that either does nothing, or, better, preserves the original password somewhere.
Most likely though you have two password fields in your form where the user is required to confirm the password. In this case, you perform your password validation rules on the second password field. This can automatically happen in a custom validation rule, remember that you have access to all other fields inside a validation function via $this->data. You can then confirm that the two passwords are identical as described here.
It works this way for me (in the model):
public $validate = array(
'password' => array(
'minLength' => array(
'rule' => array('minLength', '8')
)
)
);
If you want to do more validations then create a custom validation method in the appropriate model. In the custom validation method hash password this way: Security::hash($this->data['User']['password'], null, true)