Implementation of login function in the YII framework of PHP

Source: Internet
Author: User
Tags sha1 sha1 encryption yii
This article mainly introduces the implementation of the login function in the YII framework of PHP in detail, including the function of automatic login through cookies, the friend who needs to refer to the following

The landing mechanism of YII

Yii has provided the most basic user login mechanism when generating the application. We use YII to generate a new application, into the protected/components directory, we can see the useridentity.php file, inside the Useridentity class there is only one public function is as follows:

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 within the components, will be loaded at the beginning of the application, for the most basic user authentication, you can see that the function was initially simply defined two user demo and admin, and the password is only demo and admin, if so if your users are very limited, Can be directly in here to modify the addition of users on the line, many words we say later. The If else under function is used to check if the user name and password are valid, and generates ERROR_USERNAME_INVALID,ERROR_PASSWORD_INVALID errors when they occur. In general, there is a real user name password verification, and the basic logic processing after landing.
This class is still not visible in the login control process. Following the principles of Model/control/view, we can see that the landing process is reflected in these three aspects. First enter the Models folder, you can see a loginform class file, this class inherits Cformmodel, for the form model of the derived class, encapsulates the data about the landing and business logic. The functions that compare cores are as follows:

/**  * Authenticates the password.  * 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 ', ' Username 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===useridentity::error_none)   {     $duration = $this->rememberme? 3600*24*30:0;     Yii::app ()->user->login ($this->_identity, $duration);     return true;   }   else     return false;}

The authenticate uses the Useridentity class to verify the username and password, and the login function will log on to the login function provided by YII by detecting if the user's identity has been set and the error code is empty. $duration can set the validity period of an identity.
Look at Control, in Sitecontroler there is an action is about the login, is Actionlogin, the function is as follows:

/**  * Displays the login page  */Public Function Actionlogin () {   if (!defined (' crypt_blowfish ') | |! Crypt_blowfish)     throw new Chttpexception ("This application requires, PHP is compiled with BLOWFISH support fo R 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->logi N ())       $this->redirect (Yii::app ()->user->returnurl);   }   Display the login form   $this->render (' login ', array (' model ' = ' $model) ');

The login action is based on LoginForm to validate the POST form to log in or render a new login page.

Finally, the view file is the site folder login.php, this is what you see the login interface.

Combing, we can clearly see YII user login Logic processing, when you enter the user name password in the login interface, the form will POST the data to the Site/login action, loign instantiate a loginform form model, and according to model V The Alidate function and the login function perform login detection, and validate validates the form data according to rule rules, where password validation requires authenticate functions, while the authenticate and login functions are verified as base To the authenticate function of useridentity. So, if we change the login logic, Lgoinform and loginaction can not be modified, directly change the useridentity authenticate function is basically possible.

The above analysis is Yii automatically generated by the user login logic processing code, it seems to be very decent, right? But our system generally to support a lot of user access, in the code to simply list the user name and password is obviously irrational, more mature of course, please database to help us manage. Let's say we create an admin table in our database by following the Mysql statement:

drop table if exists ' admin '; CREATE table ' admin ' (   ' admin_id ' int unsigned not NULL auto_increment comment ' primary key ',   ' username ' varchar (+) not Nu ll comment ' login name ',   ' PSW ' char (+) NOT null comment ' login password (two times SHA1) ',   ' nick ' varchar ' not null comment ' nickname ',   ' a Dd_time ' datetime NOT NULL comment ' creation time ',   ' login_time ' datetime null comment ' recent login time ',   unique key (' username '), C7/>primary key (' admin_id ')) engine=innodb default Charset=utf8 comment= ' Administrator table ';

When the Mysql build table is complete, we use the GII to generate the admin model, and then we can go back to our original Component useridentity.php rewrite authenticate function to implement our own user name password verification. For the sake of security, the password uses two SHA1 encryption, so the collected password two times SHA1 encryption, and then in the Admin we created to find out if there is a username corresponding to the form input user, and then the password than the encryption, if you can pass the user's common information by The SetState function is set to the user field of Yii, such as $this->setstate (' Nick ', $user->nick); After this sentence, you can access the current user's nickname directly through Yii:app ()->user->nick, instead of querying the database. and $user->login_time = Date (' y-m-d h:i:s '); is to update the user login time and save to the database by saving the next sentence.

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; }

And if you want to change the login interface, then enter the view inside the site folder in the login.php, indulge in tossing it into the way you want to look, so that our own landing process has been completed. With Yii is not very convenient ~

Set up automatic login
The principle of automatic login is simple. The main thing is to use cookies to achieve
On the first login, if the login is successful and the next automatic login is selected, the user's authentication information will be saved to the cookie and the cookie is valid for 1 years or several months.

The next time you log in to determine whether the cookie stores the user's information, if there is a cookie stored in the user information to log in,

Configuring the User Component

First set up the user component in the configuration file components

    ' User ' = [      ' identityclass ' = ' app\models\user ',      ' enableautologin ' = True,    ],

We see Enableautologin is used to determine whether to enable the automatic login function, this and the interface on the next automatic login Independent.
Only if Enableautologin is true, if the next automatic login is selected, the user information is stored in the cookie and the cookie is set to be valid for 3600*24*30 seconds for the next logon

Now let's look at how it's implemented in Yii.

First Login and save cookies

1 login Function of 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, simply log in, then execute the Switchidentity method and set the authentication information.

2, Switchidentity set up certification information

  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 more important and needs to be called when exiting.

There are three main functions of this method
Set the duration of the session
If the cookie is valid for more than 0 and allows automatic login, the user's authentication information is saved to the cookie
If you allow automatic login, delete cookie information. This is called when the exit is used. The $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 the user model must implement the Identityinterface interface when setting up the user component. Therefore, the first two values can be obtained in the user model, and the third value is the expiration date of the cookie.

Second, automatically log in from the cookie

From the above we know that the user's authentication information has been stored in the cookie, then the next time directly from the cookie to take information and then set it up.

1. AccessControl User Access control

Yii provides accesscontrol to determine if a user is logged in, and with this it does not need to be judged in every action.

Public function behaviors ()  {    return [      ' access ' + = '        class ' = Accesscontrol::classname (),        ' only ' + = [' logout '],        ' rules ' = ['          actions ' and ' = '            logout '],            ' Allow ' =            ' Roles ' = = [' @ '],], [],]      ,    ];  

2, Getisguest, getidentity judge whether to authenticate users

Isguest is the most important attribute in the automatic login process.
In the above AccessControl access control through the Isguest property to determine whether it is authenticated users, and then in the Getisguest method is called Getidentity to obtain user information, if not empty is authenticated users, otherwise is the visitor (not logged in).

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 re-generate 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-&GT;AUTHTIMEOUTP      Aram);      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 of the first through the session to determine the user, because the user login has already existed in the session. Then, if you are automatically logged in, you can log in using cookie information.

4. Log in Loginbycookie by storing 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__); }      }    }  }

The cookie value is read First, then $data = Json_decode ($value, True), and deserialized into an array.

This code from the above can know that to achieve automatic login, these three values must have a value. In addition, the findidentity and Validateauthkey methods must be implemented in the user model.

Once the login is complete, you can also reset the cookie expiration date so that it works together.

$this->switchidentity ($identity, $this->autorenewcookie? $duration: 0);

Third, exit logout

 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 ();    The 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, $durati      ON); }} elseif ($this->enableautologin) {Yii:: $app->getresponse ()->getcookies ()->remove (New Cookie ($this-    >identitycookie)); }  }

When exiting, set the current authentication to null and then determine if the automatic login function will delete the relevant cookie information.

The above is the whole content of this article, I hope that everyone's learning has helped, more relevant content please pay attention to topic.alibabacloud.com!

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.