problem with login from database

I created the following table:




CREATE TABLE `sitetb_users` (

   `id` int(10) NOT NULL AUTO_INCREMENT,

   `username` varchar(20) NOT NULL,

   `password` varchar(20) NOT NULL,

   `auth_key` varchar(100) NOT NULL DEFAULT '',

   `access_token` varchar(100) NOT NULL DEFAULT '',

   `email` varchar(25) NOT NULL,

   `phone_number` varchar(20) DEFAULT NULL,

   `user_type` varchar(10) DEFAULT NULL,

   PRIMARY KEY (`id`),

   UNIQUE KEY `username` (`username`),

   UNIQUE KEY `email` (`email`)

)

ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8



then I executed the following code:




<?php

$id=1;

$username='khaled';

$password='retyppp';

$auth_key=md5($id);

$access_token=sha1($username.':'.$password);

$email='khaled@ket.com';

$phone_number='20235634253';

$user_type='owner';

mysql_query(

   "insert into sitetb_users values(

        $id,

		'$username',

		'$password',

		'$auth_key',

		'$access_token',

		'$email',

		'$phone_number',

		'$user_type'

	)"

);

$id=2;

$username='muhammad';

$password='poestmp';

$auth_key=md5($id);

$access_token=sha1($username.':'.$password);

$email='muhammad@ket.com';

$phone_number='20235634253';

$user_type='forman';

mysql_query(

   "insert into sitetb_users values(

        $id,

		'$username',

		'$password',

		'$auth_key',

		'$access_token',

		'$email',

		'$phone_number',

		'$user_type'

	)"

);



In the component section of my config:




'user' => [

            'identityClass' => 'app\models\SitetbUsers',

            'enableAutoLogin' => false,

        ],



In models\SitetbUsers.php




<?php


namespace app\models;


use Yii;

use yii\base\NotSupportedException;

use yii\db\ActiveRecord;

use yii\helpers\Security;

use yii\web\IdentityInterface;


class SitetbUsers extends \yii\db\ActiveRecord  implements IdentityInterface

{

    public static function tableName()

    {

        return '{{%users}}';

    }

	

    public function rules()

    {

        return [

            [['username', 'password', 'email'], 'required'],

            [['username', 'password', 'phone_number'], 'string', 'max' => 20],

            [['auth_key', 'access_token'], 'string', 'max' => 100],

            [['email'], 'string', 'max' => 25],

            [['user_type'], 'string', 'max' => 10],

            [['username'], 'unique'],

            [['email'], 'unique']

        ];

    }


    public function attributeLabels()

    {

        return [

            'id' => Yii::t('app', 'ID'),

            'username' => Yii::t('app', 'Username'),

            'password' => Yii::t('app', 'Password'),

            'auth_key' => Yii::t('app', 'Auth Key'),

            'access_token' => Yii::t('app', 'Access Token'),

            'email' => Yii::t('app', 'Email'),

            'phone_number' => Yii::t('app', 'Phone Number'),

            'user_type' => Yii::t('app', 'User Type'),

        ];

    }

	

    public static function findIdentity($id)

    {

        return static::findOne($id);

    }


    public static function findIdentityByAccessToken($token, $type = null)

    {

          return static::findOne(['access_token' => $token]);

    }

 

    public static function findIdentityByAccessToken($token)

    {

        throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');

    }


    public static function findByUsername($username)

    {

        return static::findOne(['username' => $username]);

    }


    public function getId()

    {

        return $this->getPrimaryKey();

    }


    public function getAuthKey()

    {

        return $this->auth_key;

    }


    public function validateAuthKey($authKey)

    {

        return $this->getAuthKey() === $authKey;

    }


    public function validatePassword($password)

    {

        return $this->password === $password;

    }


}



In models\LoginForm.php




<?php


namespace app\models;


use Yii;

use yii\base\Model;


class LoginForm extends Model

{

    public $username;

    public $password;

    public $rememberMe = true;


    private $_user = false;

   

    public function rules()

    {

        return [

            [['username', 'password'], 'required'],

            ['rememberMe', 'boolean'],

            ['password', 'validatePassword'],

        ];

    }

   

    public function validatePassword($attribute, $params)

    {

        if (!$this->hasErrors()) {

            $user = $this->getUser();


            if (!$user || !$user->validatePassword($this->password)) {

                $this->addError($attribute, 'Incorrect username or password.');

            }

        }

    }

   

    public function login()

    {

        if ($this->validate()) {

            return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0);

        } else {

            return false;

        }

    }

   

    public function getUser()

    {

        if ($this->_user === false) {

            $this->_user = User::findByUsername($this->username);

        }


        return $this->_user;

    }

}



In controllers\SiteController.php




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,

            ]);

        }

    }


    public function actionLogout()

    {

        Yii::$app->user->logout();


        return $this->goHome();

    }



The problem is: when I try login , the result is "Incorrect username or password."

First:

since it seems that you really want to stay your code as it is (depending on db create query) you should not use a password like this - encrypt it and use longer password field.

Second:

You dont need to write SQL to create your objects in database. Since your extending ActiveRecord-Class, you can use its "create"-function.




$user = SitetbUsers::create($array_with_data) // Array have to contain all required fields as key - value is required database value then, e.g. ['username' => 'Jeff', 'password' => 'xhn34nr3x' [...]]

// Since you have to work with some values before submitting data, you can overwrite this method:


class SitetbUsers extends \yii\db\ActiveRecord  implements IdentityInterface {


// code from my application, you have to fix missing or wrong fields!

    static public function create($values) {

        $this->hashPassword($values['password']);

        

        $values['password'] = $values['password'];

        $values['auth_key'] = Yii::$app->getSecurity()->generateRandomString();

        $values['access_token'] = Yii::$app->getSecurity()->generateRandomString();

        $values['status'] = isset($values['status']) ? $values['status'] : -1;

        

        $user = parent::create($values);

        UserRole::create([

            'user_id' => $user->id,

            'role_id' => Role::findOne(['name' => 'user'])->id,

        ]);

        

        return $user;

    }

}



Using this code, you can also use this validate function for password - also you have to fix missing or wrong fields:




    /**

     * Validates password

     *

     * @param  string  $password password to validate

     * @return boolean if password provided is valid for current user

     */

    public function validatePassword($password) {

        list($hash, $result) = explode(".", $this->password);

        $hashed_pw = hash("sha256", $hash.$password);

        return $hashed_pw === $result;

    }



Please notify that this function is hashing password since its not saved in clear text - you have to change it here or add corresponding code in create function!

I think (but im not sure) your issue your findByUsername-Function:




    public static function findByUsername($username)

    {

        return static::findOne(['username' => $username]);

    }

// try to change as following

    public static function findByUsername($username)

    {

        return self::findOne(['username' => $username]);

    }



I only use "static" for creating instances from current class in static call




return new static($arguments)



so im not sure is this working for refering self as function call…

Here some snippets from my Account-Class, which is solving login / register and similar tasks




// ...

[

    ['username', 'password'], 

    'required', 

    'message' => 'Dieses Feld muss ausgefüllt werden',

    'on' => 'login',

],


// ...

[

    ['username', 'password'],

    'validateLogonData',

    'on' => 'login',

],


// ...

// user->active check is a user marked as active user in database, since i have to check all registrations manually

public function validateLogonData($attribute, $params) {

    if (!$this->hasErrors()) {

        $user = $this->getUser();


        if (!$user || !$user->validatePassword($this->password) || !$user->active()) {

            $this->addError($attribute, 'Falscher Benutzername oder Passwort.');

        }

    }

}


// ...

private function getUser() {

    if ($this->_user === false) {

        $this->_user = User::findOne(['name' => $this->username]);

    }


    return $this->_user;

}



I hope that i helped a bit