Yii Framework 2.0 Login with User Database

Yii Framework 2.0 Login With User Database

You can implement database user management using extesions like https://github.com/amnah/yii2-user.

OR

If you want to write your own custom script to manage the users you can override Yii2 identityClass.

In the component section of your config add:

'user' => [
'identityClass' => 'app\models\User',
'enableAutoLogin' => true,
],

Please note that your user model MUST IMPLEMENT \yii\web\IdentityInterface

Here is the example of the model class that you can use to implement database authentication


namespace app\models;

//app\models\gii\Users is the model generated using Gii from users table

use app\models\gii\Users as DbUser;

class User extends \yii\base\Object implements \yii\web\IdentityInterface {

public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
public $email;
public $phone_number;
public $user_type;

/**
* @inheritdoc
*/
public static function findIdentity($id) {
$dbUser = DbUser::find()
->where([
"id" => $id
])
->one();
if (!count($dbUser)) {
return null;
}
return new static($dbUser);
}

/**
* @inheritdoc
*/
public static function findIdentityByAccessToken($token, $userType = null) {

$dbUser = DbUser::find()
->where(["accessToken" => $token])
->one();
if (!count($dbUser)) {
return null;
}
return new static($dbUser);
}

/**
* Finds user by username
*
* @param string $username
* @return static|null
*/
public static function findByUsername($username) {
$dbUser = DbUser::find()
->where([
"username" => $username
])
->one();
if (!count($dbUser)) {
return null;
}
return new static($dbUser);
}

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

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

/**
* @inheritdoc
*/
public function validateAuthKey($authKey) {
return $this->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;
}

}

I hope that would be helpful to you . Cheers :)

Yii2 framework cannot login using a custom database

I answer my own question. I added the following code in the find

  public static function findByUsername($username, $password)
{
$user = self::find()->where(['USR_USERNAME' => $username, 'USR_STATUS' => '1'])->one();

if (hash('sha256', $password) == $user->USR_PASSWORD)
{
return new static($user);
}

}

now this will validate if the password is matched with the database in sha256 encryption and then on my validatePassword method I revise it to simple always return true because, on the LoginForm, they always search for the username first then check for the password validation, so If username/password is wrong it will instantly validate the user doens't exist

 public static function validatePassword($password)
{
return true;
}

I find yii2 hard, very hard with the lack of documentation.

Yii2 step-by-step guide on login from table in MySQL

Yii2 advanced app comes by default with a working example of the login part from the DB (I see the basic ones uses a static username and password). You do not have to install anything extra, just look at the code. Install the advanced app and take a look at the frontend.

In short SiteController uses LoginModel for validation then uses the login() of the LoginModel to login the User model to the User component.

If you do not want to use the User model, just create your own model and use that one. You do not want to use the default User component, just create your own. It is quite easy to do.

Edit:
mate, remove the public declarations of variables bellow.

class User extends ActiveRecord implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;

You are telling Yii to ignore what is in the database.

custom login in yii2 framework

Yii Framework 2.0 Login With User Database , This link about custom login in Yii 2.0 framework solved my above question :)

Login from Different Databases Yii2

If you use that scenario, avoid using roles "@" in your accessControl. Roles "@" only applied to Yii::$app->user, so if you login with different component (such as Yii::$app->userPerusahaan->login()) it will not count as registered user with roles "@". Modified your siteController like this example.

public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['index', 'login'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['@'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}

public function actionIndex()
{
if(Yii::$app->user->isGuest && Yii::$app->userPerusahaan->isGuest) return $this->redirect(['login']);
// ......

Connect Yii2 Login form to DB

You need to change in User.php model (mainly three methods findIdentity, findByUsername, validatePassword). Below link will surely help you to go through this.
Link 1, Link 2 and Link 3

<?php

namespace app\models;
use app\models\Users; // generated using Gii; user master table in db

class User extends \yii\base\Object implements \yii\web\IdentityInterface
{
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;

/**
* @inheritdoc
*/
public static function findIdentity($id)
{
$user = Users::findOne(['id'=>$id]);
if(!$user)
{
return null;
}
else
{
$user_info =
[
'id' => $user->id,
'username' => $user->username,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => $user->email,
'image'=>$user->image,
// assign other attributes too if needed
];
return new static($user_info);
}
}

/**
* Finds user by username
*
* @param string $username
* @return static|null
*/
public static function findByUsername($username)
{
$user = Users::findOne(['id'=>$id]);
if(!$user)
{
return null;
}
else
{
$user_info =
[
'id' => $user->id,
'username' => $user->username,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'email' => $user->email,
'image'=>$user->image,
// assign other attributes, too if needed
];
return new static($user_info);
}

return null;
}

/**
* 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; // apply any encryption algo here to $password, if you have used any
}

// ...
// ... other functions here
}

Yii2 Login with database

You should make sure you change the getUser() method on models/LoginForm.php to use your Member model class, otherwise it will keep validating against the default User model.

public function getUser() {
if ($this->_user === false) {
$this->_user = Member::findByUsername($this->username);
}
return $this->_user;
}

Also, here is an example of my own User model class

namespace app\models;

use Yii;

class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface {
const SCENARIO_LOGIN = 'login';
const SCENARIO_CREATE = 'create';

public static function tableName() {
return 'user';
}

public function scenarios() {
$scenarios = parent::scenarios();
$scenarios[self::SCENARIO_LOGIN] = ['username', 'password'];
$scenarios[self::SCENARIO_CREATE] = ['username', 'password', 'authKey'];
return $scenarios;
}

public function rules() {
return [
[['username', 'email'], 'string', 'max' => 45],
[['email'], 'email'],
[['password'], 'string', 'max' => 60],
[['authKey'], 'string', 'max' => 32],

[['username', 'password', 'email'], 'required', 'on' => self::SCENARIO_CREATE],
[['authKey'], 'default', 'on' => self::SCENARIO_CREATE, 'value' => Yii::$app->getSecurity()->generateRandomString()],
[['password'], 'filter', 'on' => self::SCENARIO_CREATE, 'filter' => function($value) {
return Yii::$app->getSecurity()->generatePasswordHash($value);
}],

[['username', 'password'], 'required', 'on' => self::SCENARIO_LOGIN],

[['username'], 'unique'],
[['email'], 'unique'],
[['authKey'], 'unique'],
];
}

public function attributeLabels() {
return [
'id' => 'Id',
'username' => 'Username',
'password' => 'Password',
'email' => 'Email',
'authKey' => 'authKey',
];
}

public static function findIdentity($id) {
return self::findOne($id);
}

public static function findIdentityByAccessToken($token, $type = null) {
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->authKey;
}

public function validateAuthKey($authKey) {
return $this->authKey === $authKey;
}

public function validatePassword($password) {
return Yii::$app->getSecurity()->validatePassword($password, $this->password);
}
}

Make sure the methods from IdentityInterface you implement but don't want to use throw an exception, just like i do on the findIdentityByAccessToken method.



Related Topics



Leave a reply



Submit