The implementation of the login function in the Yii Framework of PHP is explained in detail. the yii Framework _ PHP Tutorial

Source: Internet
Author: User
Explain in detail the implementation of the login function in PHP Yii Framework, yii Framework. A detailed explanation of the implementation of the login function in PHP Yii Framework. the login mechanism of yii Framework Yii provides the most basic user login mechanism when generating an application. We use Yii to generate a new detailed explanation of the implementation of the login function in the PHP Yii Framework. the yii Framework

Yii login mechanism

Yii provides the most basic user login mechanism when generating an application. We use Yii to generate a new application and enter the protected/components Directory. we can see the UserIdentity. php file. there is only one public function in the UserIdentity class:

public function authenticate() {   $users=array(     // username => password     'demo'=>'demo',     'admin'=>'admin',   );   if(!isset($users[$this->username]))     $this->errorCode=self::ERROR_USERNAME_INVALID;   elseif($users[$this->username]!==$this->password)     $this->errorCode=self::ERROR_PASSWORD_INVALID;   else     $this->errorCode=self::ERROR_NONE;   return !$this->errorCode; } 

This class is in components and will be loaded at the beginning of the application for the most basic user verification. you can see that, at the beginning, this function simply defines two users, demo and admin, and the password is only demo and admin. if your users are limited, you can directly modify and add users here. we will talk about it later. The if else in the function is used to check whether the user name and password are valid. if an error occurs, errors such as ERROR_USERNAME_INVALID and ERROR_PASSWORD_INVALID are generated. In general, real user name and password verification is performed here, and the basic logic after login is processed.
The login control process cannot be seen from the perspective of this class. Following the Model/Control/View principles, we can see that the login process is reflected in these three aspects. First, go to the Models folder and you can see a LoginForm class file. this class inherits from CFormModel, which is a form model derived class and encapsulates login data and business logic. The core functions are as follows:

/*** Authenticates the password. * This is the 'authenticate' validator as declared in rules (). */public function authenticate ($ attribute, $ params) {$ this-> _ identity = new UserIdentity ($ this-> username, $ this-> password); if (! $ This-> _ identity-> authenticate () $ this-> addError ('password', 'user name or password error ');} /*** Logs in the user using the given username and password in the model. * @ return boolean whether login is successful */public function login () {if ($ this-> _ identity = null) {$ this-> _ identity = new UserIdentity ($ this-> username, $ this-> password); $ this-> _ identity-> authenticate ();} if ($ this-> _ identity-> errorCode = UserIden Tity: ERROR_NONE) {$ duration = $ this-> rememberMe? 3600*24*30: 0; // 30 days Yii: app ()-> user-> login ($ this-> _ identity, $ duration); return true ;} else return false ;}

Here, authenticate uses the UserIdentity class to verify the user name and password. the login function checks whether the user identity has been set and whether the error code is null. Finally, the login function provided by Yii is used to log on. $ Duration can be used to set the validity period of an identity.
Let's look at Control. in siteControler, there is an action about logon, that is, actionLogin. the function is as follows:

/**  * Displays the login page  */ public function actionLogin() {   if (!defined('CRYPT_BLOWFISH')||!CRYPT_BLOWFISH)     throw new CHttpException(500,"This application requires that PHP was compiled with Blowfish support for crypt().");    $model=new LoginForm;    // if it is ajax validation request   if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')   {     echo CActiveForm::validate($model);     Yii::app()->end();   }    // collect user input data   if(isset($_POST['LoginForm']))   {     $model->attributes=$_POST['LoginForm'];     // validate user input and redirect to the previous page if valid     if($model->validate() && $model->login())       $this->redirect(Yii::app()->user->returnUrl);   }   // display the login form   $this->render('login',array('model'=>$model)); } 

The login action is based on the LoginForm to verify the form of the POST or render a new login page.

Finally, the view file is login. php in the site folder, which is the login interface you see.

After sorting out, we can clearly see that Yii's user login logic processing, after you enter the user name and password on the login interface, the form will POST the data to the site/login action, loign instantiates a LoginForm form model and performs logon detection based on the validate and login functions in the model. validate verifies the form data according to the rules of the rule. the authentication of password requires the authenticate function, the authenticate and login functions are based on UserIdentity's authenticate function. Therefore, if we change the login logic, neither LgoinForm nor loginaction can be modified. simply change the authenticate function of UserIdentity.

The above analysis is the logic processing code automatically generated by Yii for user login. it looks pretty decent, doesn't it? However, our system generally needs to support access by many users. it is obviously irrational to simply list the user names and passwords in the code. to be more mature, please ask the database to help us manage them. Suppose we create an admin table in our database by following the Mysql statement below:

Drop table if exists 'admin'; create table 'admin' ('admin _ id' int unsigned not null auto_increment comment 'primary key', 'username' varchar (32) not null comment 'login name', 'psw' char (40) not null comment' login password (twice sha1) ', 'Nick' varchar (64) not null comment 'nicknames ', 'Add _ time' datetime not null comment 'creation time', 'login _ time' datetime null comment' recent logon time ', unique key ('Username'), primary key ('admin _ id') engine = innodb default charset = utf8 comment = 'Administrator table ';

After the Mysql table is created, we use gii to generate the admin Model. then we can return to UserIdentity. php in our original Component to rewrite the authenticate function to verify the user name and password. For the sake of security, the password is encrypted twice, so the collected password is encrypted twice, then, in the Admin we created, find out whether there is a user corresponding to the username entered in the form, and then compare the encrypted password, if all the information is passed, you can set the user's common information from the setState function to the user field of Yii, such as $ this-> setState ('Nick ', $ user-> nick); after this sentence, you can directly access the nickname of the current login user through Yii: app ()-> user-> nick, instead of querying the database. While $ user-> login_time = date ('Y-m-d H: I: s') is used to update the user login time, save the statement to the database.

public function authenticate() {   if(strlen($this->password) > 0)     $this->password = sha1(sha1($this->password));   $user = Admin::model()->findByAttributes(array('username' => $this->username));   if($user == null)     $this->errorCode=self::ERROR_USERNAME_INVALID;   elseif( !($user instanceof Admin) || ($user->psw != $this->password) )     $this->errorCode=self::ERROR_PASSWORD_INVALID;   else   {     $this->setState('admin_id', $user->admin_id);     $this->setState('nick', $user->nick);     $this->setState('username', $user->username);     $user->login_time = date('Y-m-d H:i:s');     $user->save();     $this->errorCode=self::ERROR_NONE;   }   return !$this->errorCode; } 

If you want to modify the login interface, enter the login in the site folder in the view. php, let it look as you want, so that our login process is complete. Is it very convenient to have Yii ~


Set automatic login
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 is saved to the cookie.
If automatic logon is allowed, the cookie information is 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:

  1. $ Identity-> getId ()
  2. $ Identity-> getAuthKey ()
  3. $ 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 into 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.

Yii login mechanism Yii provides the most basic user login mechanism when generating an application. We use Yii to generate a new...

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.