如何在yii2中使用两个不同的模型或切换身份类登录? [英] How to login using two different model or switch identity class in yii2?

查看:28
本文介绍了如何在yii2中使用两个不同的模型或切换身份类登录?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想允许用户从两个不同的模型登录.

I want to allow user login from two different model.

Config.php

'user' => [
        'identityClass' => 'app\models\User', //one more class here
        'enableAutoLogin' => false,
        'authTimeout' => 3600*2,
    ],

LoginForm.php

 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'],
    ];
}

 public function validatePassword($attribute, $params)
{
    if (!$this->hasErrors()) {
        $user = $this->getUser();

        if (!$user || !$user->validatePassword($this->password)) {
            $this->addError($attribute, Yii::t('user', '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 parentLogin()
{
    // How to validate parent Login?
}

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

    return $this->_user;
}

User.php

class User extends \yii\db\ActiveRecord implements IdentityInterface
{
    public static function tableName()
   {
    return 'users';
   }

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

  public static function findByUsername($username)
 {
    return static::findOne(['user_login_id' => $username]);
 }

Controller.php

 public function actionLogin()
{
    // Working
}

public function actionParentLogin()
{
    $model = new LoginForm();

    if ($model->load(Yii::$app->request->post()) && $model->parentLogin()) {

            $parent = ParentLogin::find()->where(['p_username' => $model->p_username])->one();
        if($parent){
            \Yii::$app->session->set('p_id',$parent->p_id);
            return $this->redirect(['parent-dashboard']);
        }
        else
        {
            Yii::$app->getSession()->setFlash('error', Yii::t('site', 'Incorrect username or password.'));
        }
    }
    return $this->render('parent-login', [
            'model' => $model,
        ]);
}

我不知道如何验证父登录.我尝试了几个小时寻找解决方法但没有成功.

I don't know how to validate parent login. I tried for hours finding workaround but not succeed.

我被困在 Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0); 因为用户表没有父登录记录.

I am stuck on Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600*24*30 : 0); because user table don't have parent login records.

我的问题

1) 是否可以有两个 identityClass.如果是,那么如何?
2) 是否可以将ParentLogin 模型扩展到User.如果是,那么如何验证?

1) Is it possible to have two identityClass. If yes then how?
2) Is it possible to extend ParentLogin model to User. If yes then how to validate?

参考资料

如何扩展用户类?
自定义 CWebUser 类
yii2 中的自定义 userIdentity 类

推荐答案

Joe Miller 有一个很好的建议,即在用户表中使用一个用户类和一些布尔字段来检查用户的角色,作为 rbac 的替代方案.但由于在您的情况下这是不可能的,这是我可以向您建议的(这种方法已经过半测试,需要采用).

Joe Miller has a good sugestion about having one user class and some boolean fields in users' table to check user's role, as an alternative to rbac. But since in your situation it is not possible, here is what I can suggest to you (this approach is half-way tested and need to be adopted).

是的,您可以拥有两个或多个 identityClass,但不能同时拥有.您需要处理身份之间的切换.所以首先,我建议你稍微编辑你的 LoginForm 模型:

Yes you can have two or more identityClasses, but not in the same time. You need to handle switching between identities. So first, I suggest to you edit your LoginForm model a little:

class LoginForm extends Model
{
    public $username;
    public $password;
    public $rememberMe = true;
    // we added this parameter to handle userModel class
    // that is responsible for getting correct user
    public $userModel;

    private $_user = false;

    /* all other methods stay same */

    /**
     * Finds user by [[username]]
     *
     * @return User|null
     */
    public function getUser()
    {
        if ($this->_user === false) {
            // calling findByUsername method dynamically
            $this->_user = call_user_func(
                [$this->userModel, 'findByUsername'], 
                $this->username
            );
        }

        return $this->_user;
    }
}

现在在控制器中:

public function actionParentLogin()
{
    $model = new LoginForm(['userModel' => ParentLogin::className()]);
    // calling model->login() here as we usually do
    if ($model->load(Yii::$app->request->post()) && $model->login()) {
            // no need to worry about checking if we found parent it's all done polymorphycally for us in LoginForm
            // here is the trick, since we loggin in via parentLogin action we set this session variable.
            Yii::$app->session->set('isParent', true);
            return $this->redirect(['parent-dashboard']);
        } else {
            Yii::$app->getSession()->setFlash('error', Yii::t('site', 'Incorrect username or password.'));
        }
    }
    return $this->render('parent-login', [
            'model' => $model,
        ]);
}

您的 parentLogin 模型应该扩展 User 模型以完成所有这些工作:

Your parentLogin model should extends User model to make all this work:

class parentLogin extends User
{
    public static function tableName()
    {
        //you parent users table name
        return 'parent_users';
    }

    public static function findByUsername($username)
    {
         return static::findOne(['p_username' => $username]);
    }
}

现在登录时需要处理身份切换,因为在配置中你有'identityClass' =>'应用\模型\用户'.我们可以使用 bootstrap 属性:

Now when you logged in, you need to handle identity switch, because in the configuration you have 'identityClass' => 'app\models\User'. We can use bootstrap property for that:

//in your config file
'bootstrap' => [
    'log',
    //component for switching identities
    'app\components\IdentitySwitcher'
],

IdentitySwitcher 类:

IdentitySwitcher class:

class IdentitySwitcher extends Component implements BootstrapInterface
{
    public function bootstrap($app)
    {
        //we set this in parentLogin action
        //so if we loggin in as a parent user it will be true
        if ($app->session->get('isParent')) {
            $app->user->identityClass = 'app\models\ParentLogin';
        }
    }
}

这篇关于如何在yii2中使用两个不同的模型或切换身份类登录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆