Yii-User I Wymuszenie Hasła W Określonych Formacie Podczas Rejestracji Użytkownika

Cześć.

Używam rozszerzenia yii-user do rejestracji użytkowników w serwisie. Wszystko jest ok, poza jedną rzeczą. Chcę wdrożyć wymuszenie reguł hasła podczas rejestracji użytkownika, tj. aby system sprawdzał, czy hasło zawiera małą literę, wielką literę, cyfrę lub znak specjalny. W związku z tym do mojego modelu: RegistrationForm dodałem taki oto wpis do funkcji rules():




	public function rules() {

		$rules = array(

array('password', 'match', 'pattern' => '/^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[\d\W]).*$/u','message' => UserModule::t("my message."))

)

} 



Reguła jest poprawna, bo poprawnie waliduje hasło, aczkolwiek pojawia się problem, gdy klikam przycisk "Zarejestruj użytkownika". Problem polega na tym, że wtedy zwraca mi hasło zahashowane, gdzie są tylko cyfry i małe litery i wtedy jest problem z walidacją - bo hasło nie spełnia wymagań…

Za hashowanie hasła odpowiada ten kod w kontrolerze RegistrationForm:




if($model->validate()&&$profile->validate())

{

$model->password=UserModule::encrypting($model->password);

$model->verifyPassword=UserModule::encrypting($model->verifyPassword);



Poniżej pełne kody kontrolera RegisterForm, modelu RegisterForm oraz modelu User, z którego RegisterForm dziediczy

Z góry dziękuję za pomoc i pozdrawiam

Tomek




Controller:


<?php


class RegistrationController extends Controller

{

	public $defaultAction = 'registration';

	

	/**

	 * Declares class-based actions.

	 */

	public function actions()

	{

		return array(

			'captcha'=>array(

				'class'=>'CCaptchaAction',

				'backColor'=>0xFFFFFF,

			),

		);

	}

	/**

	 * Registration user

	 */

	public function actionRegistration() {

            $model = new RegistrationForm;

            $profile=new Profile;

            $profile->regMode = true;

            

			// ajax validator

			if(isset($_POST['ajax']) && $_POST['ajax']==='registration-form')

			{

				echo UActiveForm::validate(array($model,$profile));

				Yii::app()->end();

			}

			

		    if (Yii::app()->user->id) {

		    	$this->redirect(Yii::app()->controller->module->profileUrl);

		    } else {

		    	if(isset($_POST['RegistrationForm'])) {

					$model->attributes=$_POST['RegistrationForm'];

					$profile->attributes=((isset($_POST['Profile'])?$_POST['Profile']:array()));

					if($model->validate()&&$profile->validate())

					{

						$soucePassword = $model->password;

						$model->activkey=UserModule::encrypting(microtime().$model->password);

						$model->password=UserModule::encrypting($model->password);

						$model->verifyPassword=UserModule::encrypting($model->verifyPassword);

						$model->superuser=0;

						$model->status=((Yii::app()->controller->module->activeAfterRegister)?User::STATUS_ACTIVE:User::STATUS_NOACTIVE);

						

						if ($model->save()) {

							$profile->user_id=$model->id;

						$model->password=UserModule::encrypting($model->password);

						$model->verifyPassword=UserModule::encrypting($model->verifyPassword);							

							$profile->save();

                                                        

                                                        //moje -  assign user the 'Authenticated' role for Rights module

                                                        $authenticatedName = Rights::module()->authenticatedName;

                                                        Rights::assign($authenticatedName, $model->id);


                                                        

							if (Yii::app()->controller->module->sendActivationMail) {

								$activation_url = $this->createAbsoluteUrl('/user/activation/activation',array("activkey" => $model->activkey, "email" => $model->email));

								UserModule::sendMail($model->email,UserModule::t("You registered from {site_name}",array('{site_name}'=>Yii::app()->name)),UserModule::t("Please activate you account go to {activation_url}",array('{activation_url}'=>$activation_url)));

							}

							

							if ((Yii::app()->controller->module->loginNotActiv||(Yii::app()->controller->module->activeAfterRegister&&Yii::app()->controller->module->sendActivationMail==false))&&Yii::app()->controller->module->autoLogin) {

									$identity=new UserIdentity($model->username,$soucePassword);

									$identity->authenticate();

									Yii::app()->user->login($identity,0);

									$this->redirect(Yii::app()->controller->module->returnUrl);

							} else {

								if (!Yii::app()->controller->module->activeAfterRegister&&!Yii::app()->controller->module->sendActivationMail) {

									Yii::app()->user->setFlash('registration',UserModule::t("Thank you for your registration. Contact Admin to activate your account."));

								} elseif(Yii::app()->controller->module->activeAfterRegister&&Yii::app()->controller->module->sendActivationMail==false) {

									Yii::app()->user->setFlash('registration',UserModule::t("Thank you for your registration. Please {{login}}.",array('{{login}}'=>CHtml::link(UserModule::t('Login'),Yii::app()->controller->module->loginUrl))));

								} elseif(Yii::app()->controller->module->loginNotActiv) {

									Yii::app()->user->setFlash('registration',UserModule::t("Thank you for your registration. Please check your email or login."));

								} else {

									Yii::app()->user->setFlash('registration',UserModule::t("Thank you for your registration. Please check your email."));

								}

								$this->refresh();

							}

						}

					} else $profile->validate();

				}

			    $this->render('/user/registration',array('model'=>$model,'profile'=>$profile));

		    }

	}

}






Model registrationform:


<?php

/**

 * RegistrationForm class.

 * RegistrationForm is the data structure for keeping

 * user registration form data. It is used by the 'registration' action of 'UserController'.

 */

class RegistrationForm extends User {

	public $verifyPassword;

	public $verifyCode;        

	

	public function rules() {

		$rules = array(

			array('username, password, verifyPassword, email', 'required'),

			array('username', 'length', 'max'=>20, 'min' => 3,'message' => UserModule::t("Incorrect username (length between 3 and 20 characters).")),

			array('password', 'length', 'max'=>128, 'min' => 8,'message' => UserModule::t("Incorrect password (minimal length 8 symbols).")),

			//my

array('password', 'match', 'pattern' => '/^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[\d\W]).*$/u','message' => UserModule::t("Hasło musi zawierać duże litery, małe litery, cyfry lub znak specjalny.")),                    

			array('email', 'email'),                 

			array('username', 'unique', 'message' => UserModule::t("This user's name already exists.")),

			array('email', 'unique', 'message' => UserModule::t("This user's email address already exists.")),

			//array('verifyPassword', 'compare', 'compareAttribute'=>'password', 'message' => UserModule::t("Retype Password is incorrect.")),

			array('username', 'match', 'pattern' => '/^[A-Za-z0-9_]+$/u','message' => UserModule::t("Incorrect symbols (A-z0-9).")),

                        //array('agree', 'required', 'requiredValue' => 1, 'message' => 'Please accept Terms and Conditons.'),                       

		);

		if (!(isset($_POST['ajax']) && $_POST['ajax']==='registration-form')) {

			array_push($rules,array('verifyCode', 'captcha', 'allowEmpty'=>!UserModule::doCaptcha('registration')));

		}

		

		array_push($rules,array('verifyPassword', 'compare', 'compareAttribute'=>'password', 'message' => UserModule::t("Retype Password is incorrect.")));

		return $rules;

	}

	

}






<?php


class User extends CActiveRecord

{

	const STATUS_NOACTIVE=0;

	const STATUS_ACTIVE=1;

	const STATUS_BANNED=-1;

	

	//TODO: Delete for next version (backward compatibility)

	const STATUS_BANED=-1;

	

	/**

	 * The followings are the available columns in table 'users':

	 * @var integer $id

	 * @var string $username

	 * @var string $password

	 * @var string $email

	 * @var string $activkey

	 * @var integer $createtime

	 * @var integer $lastvisit

	 * @var integer $superuser

	 * @var integer $status

     * @var timestamp $create_at

     * @var timestamp $lastvisit_at

	 */


	/**

	 * Returns the static model of the specified AR class.

	 * @return CActiveRecord the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return Yii::app()->getModule('user')->tableUsers;

	}


	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.CConsoleApplication

		return ((get_class(Yii::app())=='CConsoleApplication' || (get_class(Yii::app())!='CConsoleApplication' && Yii::app()->getModule('user')->isAdmin()))?array(

			array('username', 'length', 'max'=>20, 'min' => 3,'message' => UserModule::t("Incorrect username (length between 3 and 20 characters).")),

			array('password', 'length', 'max'=>128, 'min' => 8,'message' => UserModule::t("Incorrect password (minimal length 8 symbols).")),                     

			array('email', 'email'),

			array('username', 'unique', 'message' => UserModule::t("This user's name already exists.")),

			array('email', 'unique', 'message' => UserModule::t("This user's email address already exists.")),

			array('username', 'match', 'pattern' => '/^[A-Za-z0-9_]+$/u','message' => UserModule::t("Incorrect symbols (A-z0-9).")),

			array('status', 'in', 'range'=>array(self::STATUS_NOACTIVE,self::STATUS_ACTIVE,self::STATUS_BANNED)),

			array('superuser', 'in', 'range'=>array(0,1)),

            array('create_at', 'default', 'value' => date('Y-m-d H:i:s'), 'setOnEmpty' => true, 'on' => 'insert'),

            array('lastvisit_at', 'default', 'value' => '0000-00-00 00:00:00', 'setOnEmpty' => true, 'on' => 'insert'),

			array('username, email, superuser, status', 'required'),

			array('superuser, status', 'numerical', 'integerOnly'=>true),

			array('id, username, password, email, activkey, create_at, lastvisit_at, superuser, status', 'safe', 'on'=>'search'),

		)<img src='http://www.yiiframework.com/forum/public/style_emoticons/default/sad.gif' class='bbc_emoticon' alt=':(' />(Yii::app()->user->id==$this->id)?array(

			array('username, email', 'required'),

			array('username', 'length', 'max'=>20, 'min' => 3,'message' => UserModule::t("Incorrect username (length between 3 and 20 characters).")),

			array('email', 'email'),

			array('username', 'unique', 'message' => UserModule::t("This user's name already exists.")),

			array('username', 'match', 'pattern' => '/^[A-Za-z0-9_]+$/u','message' => UserModule::t("Incorrect symbols (A-z0-9).")),

			array('email', 'unique', 'message' => UserModule::t("This user's email address already exists.")),

		):array()));

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

        $relations = Yii::app()->getModule('user')->relations;

        if (!isset($relations['profile']))

            $relations['profile'] = array(self::HAS_ONE, 'Profile', 'user_id');

        return $relations;

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'id' => UserModule::t("Id"),

			'username'=>UserModule::t("username"),

			'password'=>UserModule::t("password"),                  

			'verifyPassword'=>UserModule::t("Retype Password"),

			'email'=>UserModule::t("E-mail"),

			'verifyCode'=>UserModule::t("Verification Code"),

			'activkey' => UserModule::t("activation key"),

			'createtime' => UserModule::t("Registration date"),

			'create_at' => UserModule::t("Registration date"),

			

			'lastvisit_at' => UserModule::t("Last visit"),

			'superuser' => UserModule::t("Superuser"),

			'status' => UserModule::t("Status"),

		);

	}

	

	public function scopes()

    {

        return array(

            'active'=>array(

                'condition'=>'status='.self::STATUS_ACTIVE,

            ),

            'notactive'=>array(

                'condition'=>'status='.self::STATUS_NOACTIVE,

            ),

            'banned'=>array(

                'condition'=>'status='.self::STATUS_BANNED,

            ),

            'superuser'=>array(

                'condition'=>'superuser=1',

            ),

            'notsafe'=>array(

            	'select' => 'id, username, password, email, activkey, create_at, lastvisit_at, superuser, status',

            ),

        );

    }

	

	public function defaultScope()

    {

        return CMap::mergeArray(Yii::app()->getModule('user')->defaultScope,array(

            'alias'=>'user',

            'select' => 'user.id, user.username, user.email, user.create_at, user.lastvisit_at, user.superuser, user.status',

        ));

    }

	

	public static function itemAlias($type,$code=NULL) {

		$_items = array(

			'UserStatus' => array(

				self::STATUS_NOACTIVE => UserModule::t('Not active'),

				self::STATUS_ACTIVE => UserModule::t('Active'),

				self::STATUS_BANNED => UserModule::t('Banned'),

			),

			'AdminStatus' => array(

				'0' => UserModule::t('No'),

				'1' => UserModule::t('Yes'),

			),

		);

		if (isset($code))

			return isset($_items[$type][$code]) ? $_items[$type][$code] : false;

		else

			return isset($_items[$type]) ? $_items[$type] : false;

	}

	

/**

     * Retrieves a list of models based on the current search/filter conditions.

     * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

     */

    public function search()

    {

        // Warning: Please modify the following code to remove attributes that

        // should not be searched.


        $criteria=new CDbCriteria;

        

        $criteria->compare('id',$this->id);

        $criteria->compare('username',$this->username,true);

        $criteria->compare('password',$this->password);

        $criteria->compare('email',$this->email,true);

        $criteria->compare('activkey',$this->activkey);

        $criteria->compare('create_at',$this->create_at);

        $criteria->compare('lastvisit_at',$this->lastvisit_at);

        $criteria->compare('superuser',$this->superuser);

        $criteria->compare('status',$this->status);


        return new CActiveDataProvider(get_class($this), array(

            'criteria'=>$criteria,

        	'pagination'=>array(

				'pageSize'=>Yii::app()->getModule('user')->user_page_size,

			),

        ));

    }


    public function getCreatetime() {

        return strtotime($this->create_at);

    }


    public function setCreatetime($value) {

        $this->create_at=date('Y-m-d H:i:s',$value);

    }


    public function getLastvisit() {

        return strtotime($this->lastvisit_at);

    }


    public function setLastvisit($value) {

        $this->lastvisit_at=date('Y-m-d H:i:s',$value);

    }

}



Witam,

skoro w funkcji actionRegistration sprawdzasz dane przed hashowaniem:

to wywołaj później $model->save(false). Powinno to rozwiązać problem.

To jeżeli chcesz zachować obecny ‘kształt’ kodu. Polecam jednak przejrzeć linia po linii i upewnić się, że wszystko jest na swoim miejscu. Na przykład:


$model->activkey=UserModule::encrypting(microtime().$model->password);

$model->password=UserModule::encrypting($model->password);

$model->verifyPassword=UserModule::encrypting($model->verifyPassword);

nie powinny moim zdaniem absolutnie znajdować się w kontrolerze. Jest to typowe działanie do wykonania po validacji, a przed zapisem czyli do funkcji beforeSave() lub ewentualnie afterValidate() w modelu. Podobnie z zapisem profilu czy też przypisaniem uprawnień w module Rights.

Witam. Jako nowy użytkownik yii chciałbym się zapytać czy to te rozszerzenie użyłeś http://www.yiiframework.com/extension/yii-user-management ? Jeżeli tak to czy instalacja tego wywołała niechciane problemy ? W komentarzach ludzie zgłaszają dużo problemów stąd moje pytanie ;)