Google style sign out of all other sessions

You are viewing revision #4 of this wiki article.
This version may not be up to date with the latest version.
You may want to view the differences to the latest version.

next (#5) »

In this wiki I will show how could logout from all other sessions or all other places.

You need a table where you can store details about user login like - IP, User id, Browser Info, Date & Time etc.

Create a table - user_login_details

CREATE TABLE `user_login_details` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `Userid` int(11) NOT NULL,
  `IP` varchar(100) DEFAULT NULL,
  `Useragent` varchar(1000) NOT NULL,
  `Createdon` datetime DEFAULT NULL,
  `Status` int(11) NOT NULL DEFAULT '1' COMMENT '1=>Active Session 0=>Inactive Session',
  PRIMARY KEY (`id`),
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Now you need to generate model. eg. - UserLoginDetails

In your main/config.php -

Within the primary array, We need to add these:

// behaviors
'behaviors' => array(
    'onBeginRequest' => array(
        'class' => 'application.components.ActiveSession'
    )
),
// application components
'user'=>array(
    // enable cookie-based authentication
    'allowAutoLogin'=>true,
    'loginUrl' => array('site/login'), //login page url
  ),

In your components -

1. Create a file called WebUser.php into components directory. In which needs to define the WebUser class, which should be an extension of the Yii CWebUser class. Within that class, we will defined a method afterLogin().

After the successfully authentication, afterLogin() will call and store the records into table user_login_details like - (Userid, IP, Useragent, Createdon, Status).

Here we will use some yii public methods-

eg. -

class WebUser extends CWebUser {
	
	public function afterLogin()
	{
		if (parent::beforeLogout()) {

			$loginDetail = new UserLoginDetails;  
			
			$loginDetail->Userid = Yii::app()->user->id; //Login user id
			$loginDetail->IP = Yii::app()->request->getUserHostAddress(); //User IP address
			$loginDetail->Useragent = Yii::app()->request->getUserAgent(); //User Agent info.
			$loginDetail->Createdon = date("Y-m-d H:i:s"); //Date & time
			$loginDetail->save();
			
			Yii::app()->user->setState('currentSessionId', $loginDetail->id); //Set a variable to store Current session id.

			return true;
		} else {
			return false;
		}
	}
 }

2. Create another file called ActiveSession.php into components directory. In which needs to define the ActiveSession class, which should be an extension of the Yii CBehavior class. Within that class, only two methods need to be defined. The first is attach(), which will associate an event handler with the application and second is handleBeginRequest(), the method is to determine the conditions in which a login must be required of the user.

eg. -

class ActiveSession extends CBehavior {
	
	public function attach($owner){
		
         $owner->attachEventHandler('onBeginRequest', array($this, 'handleBeginRequest'));
      }
		
	public function handleBeginRequest($event){
			
		if (!$user->isGuest){
			
			$loginDetail = UserLoginDetails::model()->findByPk(Yii::app()->user->currentSessionId);
			
			//Before any action, it will check the status of the current user. if status is 0 then user will be logged out.
			if($loginDetail->Status == 0){

				Yii::app()->user->logout();
				
				$url = $app->createUrl(Yii::app()->homeUrl[0]);
				$app->request->redirect($url);
			}
		}	
    }
}

In your action controller -

//user login details
	public function actionDetails() {
		
		$dataProvider = new CActiveDataProvider('UserLoginDetails',
		  array('id'=>'login-detail',
		      'sort'=>array('defaultOrder'=>'id DESC', 
			  'attributes'=>array('IP', 'Useragent', 'Createdon')
			  ),
			'criteria' => array(
                  'condition' => 'Userid=:Userid',
                  'params' => array(':Userid' => Yii::app()->user->id),
                ),
			'pagination'=>array('pageSize'=>5)));
		
		$this->render('details',array());
	}
	
	
	//sign out of all other session with ajax request, it will update all the records of current user except current session record. it will be set status = 0 in user_login_details table. 
	public function actionSignoutallother() {
		
		$Userid = Yii::app()->user->id; //Current user login id
		$currentSessionId = Yii::app()->user->currentSessionId; //Current user session id
		
		if(Yii::app()->request->isAjaxRequest){

			UserLoginDetails::model()->updateAll(array('Status' => 0), 'Userid = '.$model->Id.' AND Status = 1 AND id !='.$currentSessionId);

			echo 'clean';
		}
	}

In your view (details.php) -

Display user recent login activity with help of CGridView. Also create a button with ajax request to clean or remove the others session.

$this->widget('zii.widgets.grid.CGridView',array(
		'id'=>'login-detail-grid',
		'dataProvider'=>$dataProvider,
		'template'=>'{items}',
		'enableSorting' => false, //Sorting disable here
		'columns'=>array(
			array(
				'header' => 'IP Address',
				'value' => '$data->IP',
			),
			array(
				'header' => 'Access Type',
				'value' => '$data->UserAgent',
			),
			array(
				'header' => 'Date/Time',
				'value' => 'date("D d M, Y h:i A",strtotime($data->Createdon))',
			 ),			
		),
	));
	
	//Display response message after ajax request
	echo "<div class='signoutall'></div>";
	
	//Sign out of all other sessions button with ajax request function
	echo CHtml::ajaxLink('Sign out of all other sessions', Yii::app()->createUrl('site/signoutallother'),
           array( // ajaxOptions
                'type' => 'POST',
				'success' => "function(data){ 
					$('.signoutall').html('<p>Successfully signed out of all other sessions.</p>');
				 	}",
				'error' => "function(er){ 
					$('.signoutall').html('<p>An error has occured, Try again later.</p>');
					 }",
                'data' => array('clean'=>'clean')
           ),
           array( //htmlOptions
				'class' => 'button',
           )
     );

Working perfectly, if you have any doubt or query please leave a comment.