using Yii 2 basic Non-enhanced version.
I have a crud admin authentication system. In which only the identifier, username and password are stored in the database. When the user goes to login, if the username and password are correct, they are logged in.
However, now I want these passwords to be protected, so I want to salt them and hash them. This is the part that I find difficult to do, or, moreover, where to put things.
Part 1: I have an AdminController that matches my User Model Create.php page. Part 2: I have a siteController that comes with the LoginForm model and login.php page for login.
First I will look at the first part, since it will obviously have to 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 ??: Thus, as you can see in this model, I only have the identifier, username and password coming from the database, so I take it, I will need to create one for the field in db with the name 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(); ?>
That's right, so that was part 1, the actual bit in which the hashed password should be generated and stored in the database, how can I achieve this?
We are moving well along 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, how do I integrate hashed_password for each user when I create it, and then check it at login?
I read this in the documentation, but just can't get it to work http://www.yiiframework.com/doc-2.0/guide-security-passwords.html