Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to add hashed passwords in yii2

using Yii 2 basic Not the advanced version.

I have a crud admin authentication system. Which stores just an id, username and password in the database. When the user goes to log in if the username and password are correct they are logged in.

However i now want to make these passwords secure so i want to salt and hash them. This is the part i am finding hard to do Or more so where to put things.

Part 1: I have an AdminController which goes along with my User Model Create.php page. Part 2: I have a siteController which goes along with the LoginForm model and the login.php page to log in.

I will go over part one first as it will obviously have to actually generate a hashed password here.

AdminController:

public function actionCreate()
{
    $model = new User();

    if ($model->load(Yii::$app->request->post()) && $model->save()) {
        return $this->redirect(['view', 'id' => $model->id]);
    } else {
        return $this->render('create', [
            'model' => $model,
        ]);
    }
}

User.php

    <?php

    namespace app\models;
    use yii\base\NotSupportedException;
    use yii\db\ActiveRecord;
    use yii\web\IdentityInterface;
    use yii\data\ActiveDataProvider;
    /**
     * User model
     *
     * @property integer $id
     * @property string $username
     * @property string $password
     */
class User extends ActiveRecord implements IdentityInterface
{


/**
 * @inheritdoc
 */
public static function tableName()
{
    return 'Users';
}


public function rules(){
        return [
            [['username','password'], 'required']
        ];
}



public static function findAdmins(){
    $query = self::find();

    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);

    return $dataProvider;

}


/**
 * @inheritdoc
 */
public static function findIdentity($id)
{
    return static::findOne(['id' => $id]);
}



/**
 * @inheritdoc
 */
public static function findIdentityByAccessToken($token, $type = null)
{
    throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}

/**
 * Finds user by username
 *
 * @param  string      $username
 * @return static|null
 */
public static function findByUsername($username)
{
    return static::findOne(['username' => $username]);
}

/**
 * @inheritdoc
 */
public function getId()
{
    return $this->id;
}

/**
 * @inheritdoc
 */
public function getAuthKey()
{
    return static::findOne('AuthKey');
}

/**
 * @inheritdoc
 */
public function validateAuthKey($authKey)
{
    return static::findOne(['AuthKey' => $authKey]);
}

/**
 * Validates password
 *
 * @param  string  $password password to validate
 * @return boolean if password provided is valid for current user
 */
public function validatePassword($password)
{
    return $this->password === $password;
}
}

Question??: So as you can see in this model i only have id, username and password coming from the database, so i take i will need to create one for field in db called "hashed_password"?

create.php:

<?php $form = ActiveForm::begin(); ?>

<?= $form->field($model, 'username')->textInput(['maxlength' => 50]) ?>

<?= $form->field($model, 'password')->passwordInput(['maxlength' => 50]) ?>

<div class="form-group">
    <?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end(); ?>

Right so that was part 1, the actual bit where the hashed password needs to be generated and saved into the database, how can i achieve this?

Okay moving on the Part2:

SiteController:

public function actionLogin()
{
    if (!\Yii::$app->user->isGuest) {
        return $this->goHome();
    }

    $model = new LoginForm();

    if ($model->load(Yii::$app->request->post()) && $model->login()) {
        return $this->goBack();
    } else {
        return $this->render('login', [
            'model' => $model,
        ]);
    }
}

LoginForm.php (model):

class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;

private $_user = false;


/**
 * @return array the validation rules.
 */
public function rules()
{
    return [
        // username and password are both required
        [['username', 'password'], 'required'],
        // rememberMe must be a boolean value
        ['rememberMe', 'boolean'],
        // password is validated by validatePassword()
        ['password', 'validatePassword'],
    ];
}

/**
 * Validates the password.
 * This method serves as the inline validation for password.
 *
 * @param string $attribute the attribute currently being validated
 * @param array $params the additional name-value pairs given in the rule
 */
public function validatePassword($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUser();

        if (!$user || !$user->validatePassword($this->password)) {
            $this->addError($attribute, 'Incorrect username or password.');
        }
    }
}

/**
 * Logs in a user using the provided username and password.
 * @return boolean whether the user is logged in successfully
 */
public function login()
{
    if ($this->validate()) {
        return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);
    } else {
        return false;
    }
}

/**
 * Finds user by [[username]]
 *
 * @return User|null
 */
public function getUser()
{
    if ($this->_user === false) {
        $this->_user = User::findByUsername($this->username);
    }

    return $this->_user;
}
}

Login.php:

<?php $form = ActiveForm::begin(); ?>

<?= $form->field($model, 'username'); ?> 
<?= $form->field($model, 'password')->passwordInput(); ?> 


<div class="form-group">
    <div class="col-lg-offset-1 col-lg-11">
        <?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
    </div>
</div>

So thats it, how do i integrate a hashed_password for each user when they create and then validate this upon login?

I have been reading this on the documentation but just cant get this to work http://www.yiiframework.com/doc-2.0/guide-security-passwords.html

like image 784
Matthew Smart Avatar asked Apr 07 '15 11:04

Matthew Smart


1 Answers

When you creating user, you should generate and save password hash. To generate it

\Yii::$app->security->generatePasswordHash($password);

To check it on login, change your User model which implements UserIdentity

    /**
     * Validates password
     *
     * @param  string $password password to validate
     * @return boolean if password provided is valid for current user
     */
    public function validatePassword($password)
    {
        return Yii::$app->getSecurity()->validatePassword($password, $this->password_hash);
    }

Instead of password_hash use your field from db.

like image 128
ineersa Avatar answered Oct 21 '22 01:10

ineersa