The Yii2 framework provides detailed information on how to log on, exit, and automatically log on.
This document describes how to implement the logon, logout, and automatic logon functions in the Yii2 framework. We will share this with you for your reference. The details are as follows:
The principle of automatic logon is simple. It is mainly implemented using cookies.
During the first logon, if the logon succeeds and the next automatic logon is selected, the user's authentication information will be saved to the cookie. The cookie is valid for one year or several months.
The next time you log on, first determine whether the cookie stores user information. If so, use the user information stored in the cookie to log on,
Configure the User component
First, set the user component in the components of the configuration file.
'user' => [ 'identityClass' => 'app\models\User', 'enableAutoLogin' => true,],
We can see that enableAutoLogin is used to determine whether to enable the automatic login function, which is irrelevant to the next automatic login on the interface.
If enableAutoLogin is set to true, the user information is stored in the cookie and the cookie is valid for 3600*24*30 seconds, for next login
Now let's take a look at how Yii is implemented.
I. First Login to save the cookie
1. login
public function login($identity, $duration = 0){ if ($this->beforeLogin($identity, false, $duration)) { $this->switchIdentity($identity, $duration); $id = $identity->getId(); $ip = Yii::$app->getRequest()->getUserIP(); Yii::info("User '$id' logged in from $ip with duration $duration.", __METHOD__); $this->afterLogin($identity, false, $duration); } return !$this->getIsGuest();}
Here, it is a simple login, and then execute the switchIdentity method to set authentication information.
2. Set authentication information for switchIdentity
public function switchIdentity($identity, $duration = 0){ $session = Yii::$app->getSession(); if (!YII_ENV_TEST) { $session->regenerateID(true); } $this->setIdentity($identity); $session->remove($this->idParam); $session->remove($this->authTimeoutParam); if ($identity instanceof IdentityInterface) { $session->set($this->idParam, $identity->getId()); if ($this->authTimeout !== null) { $session->set($this->authTimeoutParam, time() + $this->authTimeout); } if ($duration > 0 && $this->enableAutoLogin) { $this->sendIdentityCookie($identity, $duration); } } elseif ($this->enableAutoLogin) { Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie)); }}
This method is important. You also need to call this method when exiting.
This method has three main functions:
① Set the session Validity Period
② If the cookie validity period is greater than 0 and automatic logon is allowed, the user's authentication information will be saved to the cookie.
③ If Automatic Logon is allowed, the cookie information will be deleted. This is called when you exit. $ Identity passed in when exiting is null
protected function sendIdentityCookie($identity, $duration){ $cookie = new Cookie($this->identityCookie); $cookie->value = json_encode([ $identity->getId(), $identity->getAuthKey(), $duration, ]); $cookie->expire = time() + $duration; Yii::$app->getResponse()->getCookies()->add($cookie);}
The user information stored in the cookie contains three values:
$identity->getId()
$identity->getAuthKey()
$duration
GetId () and getAuthKey () are in the IdentityInterface interface. We also know that when setting the User component, this User Model must implement the IdentityInterface interface. Therefore, you can get the first two values in the User Model. The third value is the cookie validity period.
Ii. Automatic Login from cookie
We know from the above that the user's authentication information has been stored in the cookie, so the next time you directly retrieve the information from the cookie and then set it.
1. AccessControl user access control
Yii provides AccessControl to determine whether a user is logged on. If this happens, you do not need to judge it in every action.
public function behaviors(){ return [ 'access' => [ 'class' => AccessControl::className(), 'only' => ['logout'], 'rules' => [ [ 'actions' => ['logout'], 'allow' => true, 'roles' => ['@'], ], ], ], ];}
2. getIsGuest and getIdentity determine whether to authenticate the user
IsGuest is the most important attribute in the automatic logon process.
In the above AccessControl access control, the IsGuest attribute is used to determine whether a user is authenticated. Then, in the getIsGuest method, getIdentity is called to obtain user information. If it is not empty, it indicates that the user is authenticated, otherwise, it is a visitor (not logged on ).
public function getIsGuest($checkSession = true){ return $this->getIdentity($checkSession) === null;}public function getIdentity($checkSession = true){ if ($this->_identity === false) { if ($checkSession) { $this->renewAuthStatus(); } else { return null; } } return $this->_identity;}
3. renewAuthStatus: Regenerate user authentication information
protected function renewAuthStatus(){ $session = Yii::$app->getSession(); $id = $session->getHasSessionId() || $session->getIsActive() ? $session->get($this->idParam) : null; if ($id === null) { $identity = null; } else { /** @var IdentityInterface $class */ $class = $this->identityClass; $identity = $class::findIdentity($id); } $this->setIdentity($identity); if ($this->authTimeout !== null && $identity !== null) { $expire = $session->get($this->authTimeoutParam); if ($expire !== null && $expire < time()) { $this->logout(false); } else { $session->set($this->authTimeoutParam, time() + $this->authTimeout); } } if ($this->enableAutoLogin) { if ($this->getIsGuest()) { $this->loginByCookie(); } elseif ($this->autoRenewCookie) { $this->renewIdentityCookie(); } }}
This part first judges the user through the session, because the user has already existed in the session after login. Then, you can use the cookie information to log on automatically.
4. log on to loginByCookie through the saved Cookie Information
protected function loginByCookie(){ $name = $this->identityCookie['name']; $value = Yii::$app->getRequest()->getCookies()->getValue($name); if ($value !== null) { $data = json_decode($value, true); if (count($data) === 3 && isset($data[0], $data[1], $data[2])) { list ($id, $authKey, $duration) = $data; /** @var IdentityInterface $class */ $class = $this->identityClass; $identity = $class::findIdentity($id); if ($identity !== null && $identity->validateAuthKey($authKey)) { if ($this->beforeLogin($identity, true, $duration)) { $this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0); $ip = Yii::$app->getRequest()->getUserIP(); Yii::info("User '$id' logged in from $ip via cookie.", __METHOD__); $this->afterLogin($identity, true, $duration); } } elseif ($identity !== null) { Yii::warning("Invalid auth key attempted for user '$id': $authKey", __METHOD__); } } }}
First read the cookie value, and then$data = json_decode($value, true);
Deserialization is an array.
From the code above, we can know that all three values must have values for automatic logon. In addition, you must implement the findIdentity and validateAuthKey methods in the User Model.
After logging on, You can reset the cookie validity period so that it works together.
$this->switchIdentity($identity, $this->autoRenewCookie ? $duration : 0);
3. log out
public function logout($destroySession = true){ $identity = $this->getIdentity(); if ($identity !== null && $this->beforeLogout($identity)) { $this->switchIdentity(null); $id = $identity->getId(); $ip = Yii::$app->getRequest()->getUserIP(); Yii::info("User '$id' logged out from $ip.", __METHOD__); if ($destroySession) { Yii::$app->getSession()->destroy(); } $this->afterLogout($identity); } return $this->getIsGuest();}public function switchIdentity($identity, $duration = 0){ $session = Yii::$app->getSession(); if (!YII_ENV_TEST) { $session->regenerateID(true); } $this->setIdentity($identity); $session->remove($this->idParam); $session->remove($this->authTimeoutParam); if ($identity instanceof IdentityInterface) { $session->set($this->idParam, $identity->getId()); if ($this->authTimeout !== null) { $session->set($this->authTimeoutParam, time() + $this->authTimeout); } if ($duration > 0 && $this->enableAutoLogin) { $this->sendIdentityCookie($identity, $duration); } } elseif ($this->enableAutoLogin) { Yii::$app->getResponse()->getCookies()->remove(new Cookie($this->identityCookie)); }}
When you exit, set the current authentication to null, and then delete the related cookie information if the automatic logon function is used.