Yii Framework Forum: Registration Forms little tips - Yii Framework Forum

Jump to content

  • (3 Pages)
  • +
  • 1
  • 2
  • 3
  • You cannot start a new topic
  • You cannot reply to this topic

Registration Forms little tips Rate Topic: ***** 11 Votes

#41 User is offline   teher811 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 44
  • Joined: 25-January 10
  • Location:Glasgow, Scotland, UK

Posted 25 January 2010 - 11:10 AM

Hi all,

Im just new on the board and I started using the Yii framework only few days ago. And I love it :), I find it beautiful. I started testing it with this tutorial and tried to add more functionalities which could interest some of you.
The idea is to limit the range of characters used in a field (username for example).
Here is how to do it (working with CActiveRecord) with username:

1. Declare $usernameLegal
class RegisterForm extends CActiveRecord
{
	...
	public $usernameLegal;
	...


2. $usernameLegal is actually $username with only the allowed characters remaining. Because it's not a field of your form, it must be affected between the time the server receives post data and the time the validation process takes place => beforeValidate()
Add this function in you CActiveRecord class (in this case I allow letters, numbers and few other characters).
public function beforeValidate()
{
    	$this->usernameLegal = preg_replace('/[^A-Za-z0-9@_#?!&-]/','',$this->username);
    	return true;
}


3. Add a new rule which will compare $usernameLegal with $username, and throw a custom message error if they don't match (you don't want the default message 'Username must be repeated exactly', it won't make sense for your website user).
public function rules()
	{
		return array(
			...
			array('username', 'compare', 'compareAttribute'=>'usernameLegal', 'message'=>'Username contains illegal characters'),
			...

		);
	}


Of cource, you can play around with preg_replace and specify a list of illegal characters instead of a list of legal characters but this is strictly the same (half full glass or half empty :D). You just need to remove '^' in the preg_replace pattern. Example (will replace < > \ / ; by ' ')
preg_replace('/[<>\/\;]/','',$this->username);


I hope this helps.
0

#42 User is offline   lui10e6 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 7
  • Joined: 02-December 10

Posted 03 January 2011 - 03:22 PM

Hello, one question:
In the User Controler you do:
// Save to the user table
$user->save();
// Delete the record
$validate->delete();

This is after the user clicks to confirm his registration so you put his details in the user table and delete them from the validate table.
What happens if I try to sign up with the same email since it check uniquness against the validate table and now it would be empty?

I could just comment this delete line and all will be well, but, after 7 days the record should be deleted so the user can register with that email. Then how to make it unique by email on user table when the register is on validate table?


Thank You.
0

#43 User is offline   Byakuya 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 15
  • Joined: 02-May 11

Posted 30 July 2011 - 03:22 AM

View Postlui10e6, on 03 January 2011 - 03:22 PM, said:

Hello, one question:
In the User Controler you do:
// Save to the user table
$user->save();
// Delete the record
$validate->delete();

This is after the user clicks to confirm his registration so you put his details in the user table and delete them from the validate table.
What happens if I try to sign up with the same email since it check uniquness against the validate table and now it would be empty?

I could just comment this delete line and all will be well, but, after 7 days the record should be deleted so the user can register with that email. Then how to make it unique by email on user table when the register is on validate table?


Thank You.


Hello, i hope you find solution after half year :)

I solved this problem by using a filter:
class Validate extends CActiveRecord
{
    public function rules()
    {
        return array(
            array('email', 'checkuser'),
        );
    }

     public function checkuser($attribute,$params)
    {
        $user = User::model()->find('LOWER(email)=?', array(strtolower($this->email)));
        if ($user === null){
            return true;
        }
        $this->addError('email','Error text');
        return false;
    }
}

0

#44 User is offline   Nathan 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 40
  • Joined: 17-August 11

Posted 30 January 2012 - 08:21 AM

I've implemented the technique described above.
However I have a question - doesn't this mean that the password will be encrypted every time I call model->save()?
So what will happen if the user edits his profile, or if I want to update his last_login date or change anything on this user object - the password will get re-encrypted?
0

#45 User is offline   propelera 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 23
  • Joined: 21-February 12

Posted 23 February 2012 - 09:29 AM

Hello and thank you for such a great tutorial. I followed your steps and made some improvements (I think so). Insteed of md5 I am using Sha512 encrypting with salt key that is changing after every login, but now I got error and can't find out what is wrong with my code. If you help me I think that my improvement (that doesn't work without your help) will improve security. Here is what I have now.

It shows this error massege:
Property "Users.password2" is not defined.

/framework/db/ar/CActiveRecord.php(144)


SiteController.php

	
public function actionRegister()
	{
		$model = new Users;
		// collect user input data
		
		if(isset($_POST['ajax']) && $_POST['ajax']==='register-form')
		{
			echo CActiveForm::validate($model);
			Yii::app()->end();
		}
		
		
		if(isset($_POST['RegsiterForm']))
		{
			$model->attributes=$_POST['RegsiterForm']; // set all attributes with post values

			// NOTE Changes to any $model->value have to be performed BEFORE $model-validate() 
			// or else it won't save to the database. 

			// Check if question has a ? at the end

			// validate user input and redirect to previous page if valid
			if($model->validate())
			{
				// save user registration
				$model->save();
				$this->redirect($this->render('finished',array('model'=>$model))); // Yii::app()->user->returnUrl
			}
		}
		// display the registration model
		$this->render('register',array('model'=>$model));
	}


Register.php (The view file, form was generated from Gii)

<div class="form">

<?php $form=$this->beginWidget('CActiveForm', array(
	'id'=>'register-form',
	'enableAjaxValidation'=>true,
)); ?>

	<p class="note">Fields with <span class="required">*</span> are required.</p>

	<?php echo $form->errorSummary($model); ?>

	<div class="row">
		<?php echo $form->labelEx($model,'username'); ?>
		<?php echo $form->textField($model,'username'); ?>
		<?php echo $form->error($model,'username'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'password'); ?>
		<?php echo $form->textField($model,'password'); ?>
		<?php echo $form->error($model,'password'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'password2'); ?>
		<?php echo $form->textField($model,'password2'); ?>
		<?php echo $form->error($model,'password2'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'email'); ?>
		<?php echo $form->textField($model,'email'); ?>
		<?php echo $form->error($model,'email'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'fullname'); ?>
		<?php echo $form->textField($model,'fullname'); ?>
		<?php echo $form->error($model,'fullname'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'question'); ?>
		<?php echo $form->textField($model,'question'); ?>
		<?php echo $form->error($model,'question'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'answer'); ?>
		<?php echo $form->textField($model,'answer'); ?>
		<?php echo $form->error($model,'answer'); ?>
	</div>

	<div class="row">
		<?php echo $form->labelEx($model,'verifyCode'); ?>
		<?php echo $form->textField($model,'verifyCode'); ?>
		<?php echo $form->error($model,'verifyCode'); ?>
	</div>
	
	<div class="row buttons">
		<?php echo CHtml::submitButton('Submit'); ?>
	</div>

<?php $this->endWidget(); ?>

</div><!-- form -->


user.php (the model)

	public function rules()
	{
		// NOTE: you should only define rules for those attributes that
		// will receive user inputs.
		return array(
			array('username','length','max'=>16),
			// convert username to lower case
			array('username', 'filter', 'filter'=>'strtolower'),
			array('password','length','max'=>32, 'min'=>6),
			array('password2','length','max'=>32, 'min'=>6),
			// compare password to repeated password
			array('password', 'compare', 'compareAttribute'=>'password2'), 
			array('email, fullname', 'length', 'max'=>128),
			// make sure email is a valid email
			array('email','email'),
			// make sure username and email are unique
			array('username, email, password, salt', 'unique'), 
			// convert question to lower case
			array('question', 'filter', 'filter'=>'strtolower'),
			array('answer','length','max'=>64),
			// convert answer to lower case
			array('answer', 'filter', 'filter'=>'strtolower'),
			array('privilages, worns, status', 'numerical', 'integerOnly'=>true),
			array('privilages','length','max'=>4, 'min'=>1),
			array('worns','length','max'=>3, 'min'=>0),
			array('status','length','max'=>2, 'min'=>0),
			array('username, password, password2, salt, email, fullname, register_date, login_date, privilages, worns, status', 'required'),
			// verifyCode needs to be entered correctly
			array('verifyCode', 'captcha', 'allowEmpty'=>!extension_loaded('gd')),
		);
	}

 [..........]

	public function beforeSave()
	{
		while ($record2 === null){
			$salt = Randomness::randomString(32);
			$record2 = Users::model()->findByAttributes(array('salt'=>$salt));
		}
		$pass = hash('sha512', $this->password.$salt);
		$this->salt = $salt;
		$this->password = $pass;
		return true;
	}


and UserIdentity.php

<?php

/**
 * UserIdentity represents the data needed to identity a user.
 * It contains the authentication method that checks if the provided
 * data can identity the user.
 */
class UserIdentity extends CUserIdentity
{
	private $_id;
	
    public function authenticate()
    {
        $record=Users::model()->findByAttributes(array('username'=>$this->username));
        if($record===null)
            $this->errorCode=self::ERROR_USERNAME_INVALID;
        else if($record->password!==hash('sha512', $this->password.$record->salt))
            $this->errorCode=self::ERROR_PASSWORD_INVALID;
        else
        {
			while ($record2 !== null){
				$salt = Randomness::randomString(32);
				$record2 = Users::model()->findByAttributes(array('salt'=>$salt));
			}
			$record->salt = $salt;
			$record->password = hash('sha512', $this->password.$salt);
			$record->save;
            $this->_id=$record->id;
            $this->setState('user_id', $record->id);
			$this->setState('user_username', $record->username);
			$this->setState('user_privilages', $record->privilages);
            $this->errorCode=self::ERROR_NONE;
        }
        return !$this->errorCode;
    }
 
    public function getId()
    {
        return $this->_id;
    }
}


Also I must mention that I am using the Randomness extention .
0

#46 User is offline   Sampa 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 173
  • Joined: 18-December 11
  • Location:Stockholm,Sweden

Posted 03 March 2012 - 05:42 AM

Regarding password security, I've read and learned alot from tom[] last couple days, and I ended up doing a simple registration using this guide and his extention Randomness.

Md5,sha1 and even salted md5 is crap compared to a true random hash.
http://www.yiiframew...randomness/#hh4 I STRONGLY recommend everyone to use it and
0

#47 User is offline   af15 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 1
  • Joined: 16-July 12

Posted 16 July 2012 - 10:54 PM

Hope someone can help me..

This is my code in protected/model/RegistrationForm.php

<?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' =>4,'message' => UserModule::t("Incorrect password (minimal length 4 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('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).")),);
		
		if (isset($_POST['ajax']) && $_POST['ajax']==='registration-form') 
			return $rules;
		else 
			array_push($rules,array('verifyCode', 'captcha', 

'allowEmpty'=>!UserModule::doCaptcha('registration')));
		return $rules;
	}
	
}
?>



and this is my controllers/SiteController.php
 public function actionRegister()
        {
                $form=new User;
                // collect user input data
                if(isset($_POST['User']))
                {
                        $form->attributes=$_POST['User']; // set all attributes with post values
                        
                        // NOTE Changes to any $form->value have to be performed BEFORE $form-validate() 
                        // or else it won't save to the database. 
                        
                        // Check if question has a ? at the end
                        $last = $form->question[strlen($form->question)-1]; 
                        if($last !== "?")
                        {
                                $form->question .= '?';
                        }
                        
                        // validate user input and redirect to previous page if valid
                        if($form->validate())
                        {                               
                                // save user registration
                                $form->save();
                                $this->redirect($this->render('finished',array('form'=>$form))); // Yii::app()->user->returnUrl
                        }
                }
                // display the registration form
                $this->render('register',array('form'=>$form));
        }


and this is my view page views/site/pages/register.php
<?php
$this->pageTitle=Yii::app()->name . ' - Register';
?>
<h1>Register</h1>

<div class="yiiForm">
<?php echo CHtml::beginForm(); ?>

<?php echo CHtml::errorSummary($form); ?>

<div class="simple">
<br/>
<p class="hint" style="margin-left:70px;">
Note: Your login name must be unique and a max of 32 characters.
</p>
<?php echo CHtml::activeLabel($form,'username', array('style'=>'width:150px;')); ?>
<?php echo CHtml::activeTextField($form,'username') ?>
</div>

<div class="simple">
<?php echo CHtml::activeLabel($form,'password', array('style'=>'width:150px;')); ?>
<?php echo CHtml::activePasswordField($form,'password') ?>
</div>

<div class="simple">
<?php echo CHtml::activeLabel($form,'password2', array('style'=>'width:150px;')); ?>
<?php echo CHtml::activePasswordField($form,'password2') ?>
</div>

<div class="simple">
<?php echo CHtml::activeLabel($form,'email', array('style'=>'width:150px;')); ?>
<?php echo CHtml::activeTextField($form,'email') ?>
</div>

<br/>

<div class="simple">
<p class="hint" style="margin-left:70px;">
Note: Your secret question that will pop up for you to reset your password (if needed).
</p>
<?php echo CHtml::activeLabel($form,'question', array('style'=>'width:150px;')); ?>
<?php echo CHtml::activeTextField($form,'question') ?>
</div>

<div class="simple">
<p class="hint" style="margin-left:70px;">
Note: Your secret answer you'll need to type in when asked your secret question.
</p>
<?php echo CHtml::activeLabel($form,'answer', array('style'=>'width:150px;')); ?>
<?php echo CHtml::activeTextField($form,'answer') ?>
</div>

<br/>

<?php if(extension_loaded('gd')): ?>
<div class="simple">
        <?php echo CHtml::activeLabel($form,'verifyCode', array('style'=>'width:150px;')); ?>
        <div>
        <?php $this->widget('CCaptcha'); ?>
        <?php echo CHtml::activeTextField($form,'verifyCode'); ?>
        </div>
        <p class="hint">Please enter the letters as they are shown in the image above.
        <br/>Letters are not case-sensitive.</p>
</div>
<?php endif; ?>

<div class="action">
<?php echo CHtml::submitButton('register'); ?>
</div>

<?php echo CHtml::endForm(); ?>

</div><!-- yiiForm -->


but I have problem with this because when I click register on the menu, it will display this message

Fatal error: Call to a member function getErrors() on a non-object in C:\xampp\htdocs\yii\framework\web\helpers\CHtml.php on line 1592

I really don't know what to do because I'm still newbie using Yii.. I hope someone can help me to make a registration. Thank you
0

#48 User is offline   Bynton 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 20
  • Joined: 09-July 12

Posted 20 July 2012 - 01:18 PM

looking for more tutorials as i want to be an expert.
0

#49 User is offline   Sampa 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 173
  • Joined: 18-December 11
  • Location:Stockholm,Sweden

Posted 20 July 2012 - 03:00 PM

Quote


Fatal error: Call to a member function getErrors() on a non-object in C:\xampp\htdocs\yii\framework\web\helpers\CHtml.php on line 1592

I really don't know what to do because I'm still newbie using Yii.. I hope someone can help me to make a registration. Thank you


That is not really a yii problem, its a OOP problem. If you do not understand that error message I suggest you go thrue some tutorials on the matter.
Because it is very straight forward error message.
0

#50 User is offline   Dhiraj Pandey 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 1
  • Joined: 09-November 12

Posted 09 November 2012 - 03:11 AM

Good hack, but when I am sending an email verification mail and user comes to verify the mail id, I update the DB for a flag change. It calls the beforeSave function once again and encrypt the password once again. Any solution?
0

#51 User is offline   Igor Savinkin 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 17
  • Joined: 30-July 13

  Posted 13 September 2013 - 09:27 AM

What if i want a new user to confirm his registration by email prior to let him login?
0

#52 User is offline   Selim 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 27
  • Joined: 12-November 13
  • Location:Dhaka, Bangladesh

Posted 24 December 2013 - 01:05 AM

Awesome tutorial. I really love it. Thanks for sharing your experience. Please let us know the url for your all tutorials.
0

Share this topic:


  • (3 Pages)
  • +
  • 1
  • 2
  • 3
  • You cannot start a new topic
  • You cannot reply to this topic

2 User(s) are reading this topic
0 members, 2 guests, 0 anonymous users