Yii Framework Forum: rehash password only when changed - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

rehash password only when changed Rate Topic: ***** 1 Votes

#1 User is offline   afterMidnight 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 12
  • Joined: 06-January 10

Posted 06 January 2010 - 07:12 PM

[EDITED: this works in yii 1.0. see my reply below for code that works in yii 1.1.]

i'm new to yii, MVC-style programming and PHP. it's taken me a while to figure out how to keep hashed passwords in a database and not have them get rehashed every time you update the record. i did eventually make it work, following suggestions by Mike in this post.

i'm posting the details here, in case this is of value to any other beginners, and to see if anyone has any critique or suggestions.

the main changes were in the model code for the database table that contains user information. the database field is 'password', and i made a new, non-database model field, named 'newPassword':

class Contact extends CActiveRecord
{
	public $newPassword;  // proxy for db field "password", which will only be hashed and updated if this is non-empty

	...

	public function newPasswordValidOrEmpty($attribute, $params) {
		if (empty($this->newPassword))
			return;
		$len = strlen(utf8_decode($this->newPassword));
		if (($len >= 8)  &&  ($len <= 16))
			return;
		$this->addError('password', 'Password must be between 8 and 16 characters.');
	}

	...

	public function rules()
	{
		return array(
			array('newPassword','length','min'=>8,'max'=>16,'on'=>'create'),
			array('newPassword',newPasswordValidOrEmpty,'on'=>'update'),

	...

	public function attributeLabels()
	{
		return array(
			'newPassword' => 'password',

	...

	public function beforeSave() {
		if (!empty($this->newPassword))
			$this->Password = hash('sha256', $this->newPassword);
		return true;
	}


the views/.../_form.php needed to include 'newPassword' instead of 'password':

<?php echo CHtml::activeLabel($model,'newPassword'); ?>
<?php echo CHtml::activePasswordField($model,'newPassword',array('size'=>28,'maxlength'=>16)); ?>


finally, the value for newPassword wasn't getting copied from the HTTP POST parameters into my model. i'm not up on the details of "massive assignment" in PHP, but the following line in the controller:

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

did not end up copying newPassword, even though it is an element of $_POST['Contact'], so i added 2 lines to the controller to copy it explicitly:

	public function actionCreate()
	{
		$model=new Contact;
		if(isset($_POST['Contact']))
		{
			$model->newPassword = $_POST['Contact']['newPassword'];  // add this line
			$model->attributes=$_POST['Contact'];

	...

	public function actionUpdate()
	{
		$model=$this->loadContact();
		if(isset($_POST['Contact']))
		{
			$model->newPassword = $_POST['Contact']['newPassword'];  // add this line
			$model->attributes=$_POST['Contact'];


perhaps there's a better way to accomplish that?

anyway, that's what i have so far. i'd be happy to hear any suggested improvements to any of it.
0

#2 User is offline   afterMidnight 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 12
  • Joined: 06-January 10

Posted 08 January 2010 - 03:11 AM

well, the above worked for me in yii 1.0.11, but not in 1.1.
here's a version that works in yii 1.1.

first, the model code, which is now simpler:

class Contact extends CActiveRecord
{
	public $newPassword;  // proxy for db field "password", which will only be hashed and updated if this is non-empty

	...

	public function rules()
	{
		return array(
			array('newPassword','length','min'=>8,'max'=>16,'allowEmpty'=>false,'on'=>'insert'),
			array('newPassword','length','min'=>8,'max'=>16,'allowEmpty'=>true,'on'=>'update'),

	...

	public function attributeLabels()
	{
		return array(
			'newPassword' => 'password',

	...

	public function beforeSave() {
		if (!empty($this->newPassword))
			$this->password = hash('sha256', $this->newPassword);
		return true;
	}



in the 1.1 form, 'password' appears in 3 places instead of just 2. replace them all with 'newPassword'.

the controller changes in 1.1 are the same as for 1.0:

        public function actionCreate()
        {
                $model=new Contact;
                if(isset($_POST['Contact']))
                {
                        $model->newPassword = $_POST['Contact']['newPassword'];  // add this line
                        $model->attributes=$_POST['Contact'];

        ...

        public function actionUpdate()
        {
                $model=$this->loadContact();
                if(isset($_POST['Contact']))
                {
                        $model->newPassword = $_POST['Contact']['newPassword'];  // add this line
                        $model->attributes=$_POST['Contact'];

0

#3 User is offline   v0id3r 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 4
  • Joined: 11-January 10

Posted 15 February 2010 - 08:16 AM

I have field in DB table field named "passwordHash" and setter & getter for property "password" in my model.
In setter "setPassword": set "passwordHash" by wraping value with my hash function.
In getter "getPassword": simply return "passwordHash".

So I always use "password" property (in forms, etc).

I set attributes as array and the password is auto-hashed too.
0

#4 User is offline   delmi 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 10
  • Joined: 30-October 10
  • Location:Firenze (Italy)

Posted 10 June 2012 - 01:54 PM

View PostafterMidnight, on 08 January 2010 - 03:11 AM, said:

well, the above worked for me in yii 1.0.11, but not in 1.1.
here's a version that works in yii 1.1.

[...]


Thanks a lot,
this is the easyest but very efficient way of rehash passwords only if changed.

Ciao
A
0

#5 User is offline   Rafael Lima 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 18
  • Joined: 30-January 12

Posted 17 June 2012 - 01:52 PM

Hi all. I'm making for the user to change its password, but I have one problem: I don't want the hashed password to be displayed in the password field.

I have tried to set the password to null in the afterFind model function. It worked, but the login functionality stopped working.

I have found this post. The last comment talks about this issue, but I didn't understand much the solution he gave.

Anyone has any thoughts regarding this?

thank you
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

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