我正在使用Yii作为应用程序,我正在编写一个非常简单的用户管理,比如注册,删除和更新用户......为了更新现有用户,我需要先检查旧密码,然后再将其更改为新插入的密码。所以这里是我在表格中的字段:
username:----
old_password:---
new_password:---
我的用户表如下所示:
id, username, password
如何在使用new_password更新之前验证old_password?我知道通常的PHP编码,但我想知道是否有任何Yii技巧自动执行此操作...
提前致谢
答案 0 :(得分:10)
你不应该用垃圾污染你的模型。请始终牢记这些基本的MVC原则:
始终创建可重复使用的代码,使代码“干”(不要重复自己)
顺便说一句,用户名字段的目的是什么?由于表单仅供登录用户使用,因此可以使用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's simple MD5 hashing method.
*
* @return string Hashed password
*/
protected function createPasswordHash($password)
{
return md5($password);
}
/**
* I don't know how you access user's 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();
}
}
示例控制器操作:
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));
}
示例模板代码:
<?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 -->
模板应该足够容易创建。这段代码经过一些小的调整,可以复制和修改。粘贴到另一个Yii项目。
答案 1 :(得分:4)
简单创建一个action
,它具有更新传递的逻辑。
在这种情况下form
为action
新actionChangePass
和validate
制定目标。
可以像这样一个粗略的例子
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>.');
}
}
另外,请确保您的用户User
Model
中有$ old_password。您还可以在模型规则中进行一些验证以使新密码成为必需
也可能有一些不同的方式,但我这样做
同时创建自定义验证scenario
changePassword
答案 2 :(得分:1)
这是我个人喜欢做的事情。这是一个复杂的版本。 添加到模型两个字段,将帮助您处理密码。请注意,这两个字段在数据库中不存在,并且不存在于Gii生成的代码中。像
这样的东西class UserModel extends CActiveRecord
{
/*Password attributes*/
public $initial_password;
public $repeat_password;
//..................
}
在表单中,不要将数据库中的实际密码字段与任何输入相关联。数据库中的两个字段应与这两个字段相关联。表单的简短版本变为:
<?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)); ?>
现在我怎么知道用户更改了密码?我只是检查beforeSave()是否两个字段为空并比较它们然后更改密码。如果它们是空的那么我就完全跳过了整个事情。如此简单的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;
}
现在根据你的问题,缺少一件事。检查旧密码!您可以添加名为aold密码的新模型字段及其表单输入控件。然后在beforesave方法中(如注释所示),您可以将输入与数据库中的实际密码字段进行比较,如果匹配则更改密码。
你可以将它们作为验证规则添加到场景中,但我发现它很复杂,而且手头的时间很少,我选择了这种方法。