Yii, the best way to implement a "change user password"

I use Yii for the application, I write very simple user management, for example, registering, deleting and updating users ... To update an existing user, I need to first check the old password before changing it to the newly inserted password. So, here are the fields that I have in the form:

username:---- old_password:--- new_password:--- 

and my user table is as follows:

 id, username, password 

How can I check the old_ sleeping box before updating it with new_password? I know the usual php encoding, but I want to know if there are any Yii tricks that do this automatically ...

Thanks in advance

+7
source share
3 answers

A simple action creation that has logic to update.

Make the goal for the form new action in this case actionChangePass and validate where you want.

An example can be done as follows:

  public function actionChangePass($id) { $user = loadModel($id) if(md5($_POST['User']['old_password']) === $user->password) { $user->setScenario('changePassword'); $user->attributes = $_POST['User']; $user->password = md5($_POST['User']['new_password']); if($user->save()) Yii::app()->user->setFlash('passChanged', 'Your password has been changed <strong>successfully</strong>.'); } else { Yii::app()->user->setFlash('passChangeError', 'Your password was not changed because it did not matched the <strong>old password</strong>.'); } } 

Also make sure the user has the $ old_password User Model . You can also make some checks in the model rules to make the new password required.

there may be other ways, but I do it like

Also create your own scenario changePassword

+4
source

You should not pollute your model with garbage. Please always remember these basic principles of MVC:

  • Your controller should not know about your model implementation.
  • Do not contaminate your model with materials not related to your application business model.

Always create a reusable code, make your code “DRY” (do not repeat yourself)

By the way, what is the purpose of the username field? Since the form will be available only to registered users, the username can be accessed using Yii :: app () → user.

 <?php // models/ChangePasswordForm.php class ChangePasswordForm extends CFormModel { /** * @var string */ public $currentPassword; /** * @var string */ public $newPassword; /** * @var string */ public $newPasswordRepeat; /** * Validation rules for this form. * * @return array */ public function rules() { return array( array('currentPassword, newPassword, newPasswordRepeat', 'required'), array('currentPassword', 'validateCurrentPassword', 'message'=>'This is not your password.'), array('newPassword', 'compare', 'compareAttribute'=>'validateNewPassword'), array('newPassword', 'match', 'pattern'=>'/^[a-z0-9_\-]{5,}/i', 'message'=>'Your password does not meet our password complexity policy.'), ); } /** * I don't know your hashing policy, so I assume it simple MD5 hashing method. * * @return string Hashed password */ protected function createPasswordHash($password) { return md5($password); } /** * I don't know how you access user password as well. * * @return string */ protected function getUserPassword() { return Yii::app()->user->password; } /** * Saves the new password. */ public function saveNewPassword() { $user = UserModel::findByPk(Yii::app()->user->username); $user->password = $this->createPasswordHash($this->newPassword); $user->update(); } /** * Validates current password. * * @return bool Is password valid */ public function validateCurrentPassword() { return $this->createPasswordHash($this->currentPassword) == $this->getUserPassword(); } } 

Controller action example:

 public function actionChangePassword() { $model=new ChangePasswordForm(); if (isset($_POST['ChangePasswordForm'])) { $model->setAttributes($_POST['ChangePasswordForm']); if ($model->validate()) { $model->save(); // you can redirect here } } $this->render('changePasswordTemplate', array('model'=>$model)); } 

example template code:

  <?php echo CHtml::errorSummary($model); ?> <div class="row"> <?php echo CHtml::activeLabel($model,'currentPassword'); ?> <?php echo CHtml::activePasswordField($model,'currentPassword') ?> </div> <div class="row"> <?php echo CHtml::activeLabel($model,'newPassword'); ?> <?php echo CHtml::activePasswordField($model,'newPassword') ?> </div> <div class="row"> <?php echo CHtml::activeLabel($model,'newPasswordRepeat'); ?> <?php echo CHtml::activePasswordField($model,'newPasswordRepeat') ?> </div> <div class="row submit"> <?php echo CHtml::submitButton('Change password'); ?> </div> <?php echo CHtml::endForm(); ?> </div><!-- form --> 

The template should be simple enough to create. This code, with some minor tweaks, is ready to be copied and pasted into another Yii project.

+9
source

Here is what I personally like to do. This is a complex version of this. Add two fields to the model to help you process the password. Note that these two fields do not exist in the database and are not present in the generated Gii code. Something like

 class UserModel extends CActiveRecord { /*Password attributes*/ public $initial_password; public $repeat_password; //.................. } 

On the form, do not associate the actual password field in the database with any input. Two fields in the database must be associated with these two fields. Short version of the form:

  <?php echo $form->errorSummary($model); ?> <?php echo $form->passwordFieldRow($model,'initial_password',array('class'=>'span5','maxlength'=>128)); ?> <?php echo $form->passwordFieldRow($model,'repeat_password',array('class'=>'span5','maxlength'=>128)); ?> 

Now, how do you know if the user has changed the password? I just check beforeSave () if the two fields are empty and compare them and then change the password. If they are empty, I just skip it all. Therefore, a simple version of beforeSave:

 /** * Called before saving the model */ protected function beforeSave() { if(parent::beforeSave()) { if($this->isNewRecord) { $this->password = HashYourPass($this->initial_password); } else { //should we update password? if($this->initial_password !== '') { //encrypt password and assign to password field $this->password = HashYourPass($this->initial_password); //Check old password match here } } return true; } else return false; } 

Now, according to your question, something is missing. Verify your old password! You can add new model fields called aold password, and control the input of the form. Then, in the beforesave method (as indicated by the comment), you can compare the input with the actual password field from the database, and if they match, then change the password.

You can add them as script validation rules, but I thought it was difficult somehow and with a little time at hand I went with this method.

+1
source

All Articles