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'] = '';
}
Related
I found problem regarding my captcha validation form, for more detail here i show my code :
Captcha function
private function gbr_captcha()
{
$vals = array(
'img_path' => './captcha/',
'img_url' => base_url().'captcha/',
'font_path' => './system/fonts/impact.ttf',
'img_width' => '150',
'img_height' => 40
);
$cap = create_captcha($vals);
$datamasuk = array(
'captcha_time' => $cap['time'],
'word' => $cap['word']
);
$expiration = time()-3600;
$this->db->query("DELETE FROM captcha WHERE captcha_time < ".$expiration);
$query = $this->db->insert_string('captcha', $datamasuk);
$this->db->query($query);
return $cap['image'];
}
Captcha Validation Form
if(empty($cek))
{
$this->form_validation->set_rules('username', 'Username', 'required');
$this->form_validation->set_rules('password', 'Password', 'required');
$this->form_validation->set_rules('captcha', 'Captcha', 'trim|required');
if ($this->form_validation->run() == FALSE)
{
$frm['gbr_captcha'] = $this->gbr_captcha();
$this->load->view("app_admin/login/index",$frm);
}
else
{
$u = $this->input->post('username');
$p = $this->input->post('password');
$this->app_model->getLoginData($u,$p);
}
}
It's working to show captcha in my web, but to validate captcha inputed from user was correct or not, it's not working, I think my problem come from my validation, if there any advice to fix my code, please share, thanks..
You are storing following data into your Database
$datamasuk = array(
'captcha_time' => $cap['time'],
'word' => $cap['word']
);
IMHO there is nothing which identifies the user (like the ip address.). You wont be able to get the already generated and stored text to compare. Because you dont have anything which points to the user.
Option 1: Store more information like ip address and when you trying to validate the captcha ask the database if there is any record for the ip address.
Option 2: Store the captcha in a session like
$this->session->set_userdata("captcha", ["expires"=> time()+3600, "data" => captcha_string])
That way is easier to validate (at least for me).
I hope it was clear enough.
I think you should have a callback function in your captcha to validate if it is correct.
$this->form_validation->set_rules('captcha', 'Captcha', 'trim|required|callback_checkCaptcha');
function checkCaptcha($word){
$ip = $this->session->get_userdata("ip");
//check db/query db if the captcha word is correct
$sql = "SELECT id FROM captcha WHERE word = {$word} and ip={$ip}"
//return true or false if word exists or not
}
And secondly how can you determine that it is the exact captcha?
You can store the user ip address, or set cookies/session
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
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
I have a log in and register form that I'd like to set up on the same page.
The log in form works just fine, with dummy data already inputted in to the database that i'm using.
The issue I'm having is that I'm getting a method calling error (assumedly because I have the same post function call to two different functions.
Currently in my routes.php file I have
// route to process the form
Route::post('/', array('uses' => 'HomeController#doLogin'));
Route::post('/', array('uses' => 'HomeController#doRegister'));
And my controller file looks like this (sorry it's a little long, I thought it'd be better to provide everything instead of assuming someone can understand my question from just my explanation alone)
public function doRegister() {
$v = User::validate(Input::all());
if ( $v->passes() ) {
User::create(array(
'name'=> Input::get('name'),
'email'=> Input::get('email'),
'password'=> Hash::make(Input::get('password')),
));
return 'Thanks for registering!';
} else {
return Redirect::to('/')->withErrors($v->getMessages());
}
}
public function doLogin()
{
// validate the info, create rules for the inputs
$rules = array(
'email' => 'required|email', // make sure the email is an actual email
'password' => 'required|alphaNum|min:3' // password can only be alphanumeric and has to be greater than 3 characters
);
// run the validation rules on the inputs from the form
$validator = Validator::make(Input::all(), $rules);
// if the validator fails, redirect back to the form
if ($validator->fails()) {
return Redirect::to('/')
->withErrors($validator) // send back all errors to the login form
->withInput(Input::except('password')); // send back the input (not the password) so that we can repopulate the form
} else {
// create our user data for the authentication
$userdata = array(
'email' => Input::get('email'),
'password' => Input::get('password')
);
// attempt to do the login
if (Auth::attempt($userdata)) {
// validation successful!
// redirect them to the secure section or whatever
// return Redirect::to('secure');
// for now we'll just echo success (even though echoing in a controller is bad)
echo 'SUCCESS!';
} else {
// validation not successful, send back to form
return Redirect::to('/');
}
}
}
As far as I'm aware this is because I'm not setting which function to use correctly for my registration form.
Hopefully I've done an ok job at explaining my issue, any solution please? (rather new to laravel)
One form would post to login and the other to register
Route::post('login', array('uses' => 'HomeController#doLogin'));
Route::post('register', array('uses' => 'HomeController#doRegister'));
And then you would open the form like:
{{ Form::open(array('url' => 'login')) }}
and
{{ Form::open(array('url' => 'register')) }}
Edit:
And the forms would just be placed inside your home view for example, and then you would just redirect from the login and register methods, and not show a view.
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.