yii2 losing user identity after login redirect

2019-07-06 06:40发布

问题:

i have looked at the other similar questions, and while this one (Yii2 user identity loss after page redirection) asks pretty much the same question, there is no solution that applies to my situation.

i have created a new identity class, i have implemented all the necessary methods and implemented the IdentityInterface. note that it does NOT extend ActiveRecord, but rather extends my own base Model class that does not derive from AR.

everything seems to work fine, i can log in and be correctly authenticated. i have traced the code and i can see that my identity class is correctly set in Yii::$app->user after IdentityInterface::validatePassword() and User::login() have been called.

however, once the login succeeds and the user is redirected, Yii::$app->user contains an empty IdentityInterface, rather than the one that was there immediately prior to the redirect.

in SiteController::actionLogin(), i have modified the code from:

return $this->goHome();

to:

$tmp = $this->goHome();
// echo '<pre>';var_dump(Yii::$app->user);echo '</pre>';exit;
return($tmp);

and i can see that Yii::$app->user still has the correct identity up until the return() statement.

can anyone tell me why i am losing my identity? i have traced through everything i can think of: yii\web\Controller, yii\base\Controller, yii\web\Response, SiteController, yii\web\User, etc...

any help at all would be greatly appreciated. thanks!

回答1:

Same problem, after 3 days find solution and I it working. My User model is:

namespace app\models;

use Yii;
class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface
{
    public $username;

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

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['name', 'email', 'password'], 'required'],
            [['email'], 'unique'],
            [['role', 'status'], 'integer'],
            [['created', 'last_update'], 'safe'],
            [['name', 'email', 'password'], 'string', 'max' => 250]
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id' => 'ID',
            'name' => 'Name',
            'email' => 'Email',
            'password' => 'Password',
            'role' => 'Role',
            'status' => 'Status',
            'created' => 'Created',
            'last_update' => 'Last Update',
        ];
    }
    public function getAuthKey() {

    }

    public function getId() {
        return $this->id;
    }

    public function validateAuthKey($authKey) {

    }

    public static function findIdentity($id) {

    }

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

    }
    public static function findByEmail($email)
    {
        return static::findOne(array('email'=>$email));
    }

    public function validatePassword($password)
    {
        return $this->password === $password;
    }
}

I change:

public static function findIdentity($id) {

}

to:

public static function findIdentity($id) {
    return self::findOne(array('id'=>$id));
}

It working for me.



回答2:

try like this

  1. implement implements \yii\web\IdentityInterface for your Active record and Implement all method from \yii\web\IdentityInterface.
  2. declare $users as static variable as private static $users = []; in your class.
  3. Alter findByUsername() function for Get user details form Username. In Config file add

    'user' => ['identityClass' => 'app\models\active record class', 'enableAutoLogin' => true, ],

    class User extends \yii\db\ActiveRecord                                     
    implements\yii\web\IdentityInterface {
    
    private $_user = false;
    public $rememberMe = true;
    /*
     * static variable
     */
    private static $users = [];
    
    /**
     * @inheritdoc
     */
    public static function tableName() {
        return 'user';
    }
    
    /**
     * @inheritdoc
     */
    public function rules() {
        return [
            [['username', 'email', 'password', 'loginType'], 'required'],
    
        ];
    }
    
    /**
     * @inheritdoc
     */
    public function attributeLabels() {
        return [
            'id' => Yii::t('app', 'ID'),
            'username' => Yii::t('app', 'Username'),
    
            'email' => Yii::t('app', 'Email'),
            'password' => Yii::t('app', '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 = self::findByUsername($this->username);
        }
    
        return $this->_user;
    }
    
    public function validatePassword($password) {
        if ($this->password == md5($password)) {
            return true;
        }
        return false;
    }
    
    public static function findIdentity($id) {
        return static::findOne($id);
    }
    
    public static function findIdentityByAccessToken($token, $type = null) {
        return static::findOne(['access_token' => $token]);
    }
    
    public function getId() {
        return $this->id;
    }
    
    public function getAuthKey() {
        return $this->authkey;
    }
    
    public function validateAuthKey($authKey) {
        return $this->authkey === $authKey;
    }
    
    public static function findByUsername($username) {
        /*
         * Get Record from Usertable
         */
        $user = User::findOne(["username" => $username]);
        if (!empty($user)) {
            /* Create array with your active record like below */
            $identity_use = ['id' => $user['id'],
                'username' => $user['username'],
                'password' => $user['password'],
                'authKey' => '',
                'accessToken' =>'',];
            return new static($identity_use);
        }
        return null;
    }
    

    }



回答3:

I had the same problem. I had my custom class implementing yii\web\IdentityInterface. I made sure that session was enabled and enableAutologin was also true, but I had no luck at all.

Finally, I realized that in config/web.php there's a setting 'user' => [ 'identityClass' => 'app\models\User', 'enableAutoLogin' => true]

Of course, the identityClass is the default in a basic yii application. After setting this value to my custom class, identity was finally persisted.



回答4:

Another simple mistake that could result in session loss would be calling

$this->redirect(...);

instead of

return $this->redirect(...);

As Yii does not call die() or exit() in this method and the code on the lines following your redirect will be executed. Being used to CodeIgniter, I had assumed this and it took me days to figure it out.



回答5:

I hope this can help you

<?php

namespace app\models;

use Yii;

class User extends \yii\db\ActiveRecord implements      \yii\web\IdentityInterface {

private $_notification;

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

public function setNotification($n) {
    Yii::$app->session['user_' .$this->id . '_notification'] = $n;
}

public function getNotification() {
    $n = Yii::$app->session['user_' .$this->id . '_notification'];
    Yii::$app->session['user_' .$this->id . '_notification'] = NULL;
    return $n;
}

/**
 * @inheritdoc
 */
public function rules()
{
    return [
        [['email', 'password', 'first_name'], 'required'],
        [['role'], 'integer'],
        [['email', 'first_name'], 'string', 'max' => 128],
        [['password'], 'string', 'max' => 32]
    ];
}

/**
 * @inheritdoc
 */
public function attributeLabels()
{
    return [
        'id' => 'ID',
        'email' => 'E-mail',
        'password' => 'Пароль',
        'first_name' => 'Имя',
        'role' => 'Роль',
    ];
}

public static function findByEmail($email) {
    return self::find()->where(['email' => $email])->one();
}

public function validatePassword($password) {
    if ($this->password == md5($password)) {
        return true;
    }
    return false;
}

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

public static function findIdentityByAccessToken($token, $type = null)
{
    return static::findOne(['access_token' => $token]);
}

public function getId()
{
    return $this->id;
}

public function getAuthKey()
{
    return $this->authkey;
}

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

}