Yii2无法存储用户身份:登录会话实例传递错误修复问询
问题分析与修复方案
这个错误的核心原因很明确:Yii的yii\web\User::login()方法要求传入一个实现了yii\web\IdentityInterface的对象实例,但你传入的是一个数组——因为你在查询用户时用了asArray()->one(),把User模型实例转成了数组,不符合方法的参数要求。
下面是具体的修复步骤:
1. 修改LoginForm的login方法
去掉asArray()调用,直接获取User模型的实例,这样就能满足login()方法的参数要求。同时不需要手动修改password字段,我们可以通过更规范的方式过滤敏感信息。
修改后的login()函数代码:
public function login() { if ($this->validate()) { // 直接获取User模型实例,不要转成数组 $user = User::find()->where(['email' => $this->email])->one(); // 调用login方法并返回结果,这样SiteController里的判断能正确生效 return Yii::$app->getUser()->login($user); } return false; }
2. (可选但推荐)过滤会话中的敏感字段
如果你不想把密码、authKey这类敏感信息存入会话,可以在User模型中重写fields()方法,自动过滤这些字段:
namespace app\models; class User extends \yii\db\ActiveRecord implements \yii\web\IdentityInterface { // 你的现有方法... public function fields() { // 获取父类默认的字段列表 $fields = parent::fields(); // 移除敏感字段,不会被序列化到会话中 unset($fields['password'], $fields['authKey']); return $fields; } }
3. 验证SiteController的逻辑
你的actionLogin()代码逻辑是没问题的,修复login()方法后,&& $model->login()这部分就能正常执行,登录成功后会跳转到用户 profile 页面。
为什么之前的代码报错?
asArray()->one()会把ActiveRecord对象转换成关联数组,而Yii::$app->user->login()必须接收一个实现了IdentityInterface的对象(你的User类已经正确实现了这个接口),所以数组类型不符合要求,导致了类型错误。
内容的提问来源于stack exchange,提问作者Grigory Volkov
相关产品推荐
相关产品推荐

