参考文章:Yii 2.0学习日记:用户登陆详细解析(上)、 Yii 2.0学习日记:用户登陆详细解析(下)
1. user
组件的配置控制session
超时时间;
2. Yii::$app->user->login()
方法控制cookie
超时时间;
3. 如果两个都超时,就需要重新登录了;
4. 代码示例:
// user组件: 'user' => [ 'identityClass' => 'common\models\system\User', 'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true], 'enableAutoLogin' => true, // 启用基于 cookie 的登录 'authTimeout' => 60, // session 超时时间 ], // Yii::$app->user->login()方法: Yii::$app->user->login($this->getUser(), 120);
我们直接看User::switchIdentity()
方法,该方法设置登录用户的session和cookie:
public function switchIdentity($identity, $duration = 0) { // 精简一部分... if ($identity) { $session->set($this->idParam, $identity->getId()); // ① if ($this->authTimeout !== null) { $session->set($this->authTimeoutParam, time() + $this->authTimeout); // ② } if ($this->absoluteAuthTimeout !== null) { $session->set($this->absoluteAuthTimeoutParam, time() + $this->absoluteAuthTimeout); // ③ } if ($this->enableAutoLogin && $duration > 0) { $this->sendIdentityCookie($identity, $duration); // ④ } } }
由①处代码,会设置一个session,将用户的id保存到session id为__id
;
由②处代码,当$authTimeout
不为null
时,设置一个超时时间,session id为__expire
;
由③处代码,当$absoluteAuthTimeout
不为null
时,设置一个绝对超时时间,session id为__absoluteExpire
;
由④处代码,当$enableAutoLogin = true
并且$duration > 0
时,设置一个cookie,以便session过期后,可以通过cookie自动登录;
要实现这个功能,我们可以直接修改user
组件:
'user' => [ 'identityClass' => 'common\models\User', 'enableAutoLogin' => true, // 启用基于cookie的登录 'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true], 'authTimeout' => 600, // session超时时间 ],
但是如果直接关闭浏览器,session会销毁,登录状态也会注销。
我们可以通过调用user::login()
方法,来实现该功能($enableAutoLogin
必须为true
):
// common\models\LoginForm: public function login() { if ($this->validate()) { //return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0); return Yii::$app->user->login($this->getUser(), 1200); } return false; }
意思就是,只要cookie
还没有失效(超过1200秒),我们就可以通过cookie
来直接登录用户,而不需要重新输入用户名密码。
protected function renewAuthStatus() { $session = Yii::$app->getSession(); $id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null; if ($id === null) { $identity = null; } else { /* @var $class IdentityInterface */ $class = $this->identityClass; $identity = $class::findIdentity($id); } $this->setIdentity($identity); if ($identity !== null && ($this->authTimeout !== null || $this->absoluteAuthTimeout !== null)) { $expire = $this->authTimeout !== null ? $session->get($this->authTimeoutParam) : null; $expireAbsolute = $this->absoluteAuthTimeout !== null ? $session->get($this->absoluteAuthTimeoutParam) : null; if ($expire !== null && $expire < time() || $expireAbsolute !== null && $expireAbsolute < time()) { $this->logout(false); } elseif ($this->authTimeout !== null) { $session->set($this->authTimeoutParam, time() + $this->authTimeout); } } if ($this->enableAutoLogin) { if ($this->getIsGuest()) { $this->loginByCookie(); } elseif ($this->autoRenewCookie) { $this->renewIdentityCookie(); } } } protected function loginByCookie() { $data = $this->getIdentityAndDurationFromCookie(); if (isset($data['identity'], $data['duration'])) { $identity = $data['identity']; $duration = $data['duration']; if ($this->beforeLogin($identity, true, $duration)) { $this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0); $id = $identity->getId(); $ip = Yii::$app->getRequest()->getUserIP(); Yii::info("User '$id' logged in from $ip via cookie.", __METHOD__); $this->afterLogin($identity, true, $duration); } } }
解析上面的代码:
首先,获取session中的用户id;
然后,根据用户id获取用户信息;
接着,判断session是否过期,未过期,则更新session;已过期,则注销用户。
再接着,如果启用了基于cookie的登录:
1、如果是来宾,则获取cookie信息,未过期则自动登录用户;
2、如果不是来宾,则更新cookie信息。