7

私はアプリケーションに Yii を使用しています。ユーザーの登録、削除、更新などの非常に単純なユーザー管理を書いています...既存のユーザーを更新するには、最初に古いパスワードを確認してから、新しい挿入パスワードに変更する必要があります. だからここに私がフォームに持っているフィールドがあります:

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

私のユーザーテーブルは次のようになります。

id, username, password

new_password で更新する前に old_password を検証するにはどうすればよいですか? 私は通常の php コーディングを知っていますが、これを自動的に行う Yii のトリックがあるかどうか知りたいです...

前もって感謝します

4

3 に答える 3

9

モデルをごみで汚してはいけません。次の基本的な MVC 原則を常に念頭に置いてください。

  • コントローラーは、モデルの実装を認識してはなりません。
  • アプリケーションのビジネス モデルに関係のないものでモデルを汚染しないでください。

常に再利用可能なコードを作成し、コードを「DRY」にします (同じことを繰り返さないでください)

ところで、ユーザー名フィールドの目的は何ですか? フォームはログインしたユーザーのみが利用できるため、ユーザー名には 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 プロジェクトにコピー & ペーストする準備ができています。

于 2013-02-17T22:38:02.057 に答える
4

action更新パスのロジックを持つ単純な create aです。

この場合 、必要な方法でform新しいターゲットを作成します。actionactionChangePassvalidate

大まかな例はこのように置くことができます

    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 に $old_password があることを確認してくださいUser Model。また、モデルのルールでいくつかの検証を実行して、新しいパスワードを必須にすることもできます

いくつかの異なる方法もある可能性がありますが、私はこのようにします

また、カスタム検証を作成しますscenario changePassword

于 2012-11-05T15:02:59.260 に答える
1

個人的にやりたいと思ったのはこちら。これの複雑なバージョンです。パスワードの処理に役立つ 2 つのフィールドをモデルに追加します。これらの 2 つのフィールドはデータベースには存在せず、Gii によって生成されたコードにも存在しないことに注意してください。何かのようなもの

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

フォームでは、データベース内の実際のパスワード フィールドを入力に関連付けないでください。データベースの 2 つのフィールドは、これら 2 つのフィールドに関連付ける必要があります。フォームの短いバージョンは次のようになります。

    <?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)); ?>  

ユーザーがパスワードを変更したことをどのように知ることができますか? 2 つのフィールドが空の場合は 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;
    }

あなたの質問によると、1つ足りないことがあります。古いパスワードを確認しています! 古いパスワードと呼ばれる新しいモデル フィールドとそのフォーム入力コントロールを追加できます。次に、beforesave メソッド (コメントで示されているように) で、入力をデータベースの実際のパスワード フィールドと比較し、一致する場合はパスワードを変更します。

それらをシナリオ付きの検証ルールとして追加することもできますが、私はそれがどういうわけか複雑であることに気づき、手元にほとんど時間がなかったので、この方法を使用しました。

于 2012-11-05T15:04:29.293 に答える