You are viewing revision #7 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.
For some applications it can be advantageous for administration reasons to allow site administrators to login as other users. This is sometimes called user impersonation or "becoming that user".
This tutorial assumes you've set up a very standard Yii web application and was written when 1.1.6 was the current standard. We're also assuming you have a User model that we'll call "User". This is the model that stores your username, password, and other user related account information.
Step 1: UserIdentity
Open your protected.components.UserIdentity class. This should have an existing "authenticate" method that is called by the login form to authenticate a user. We'll begin by refactoring this method a little to pull out the actual work of saving the user.
public function authenticate()
{
$this->_user=User::model()->findByAttributes(array('username'=>$this->username));
if($this->_user===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if($this->_user->password!==$this->password)
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
$this->logInUser($this->_user);
}
return !$this->errorCode;
}
protected function logInUser($user)
{
if($user)
{
$this->_user = $user;
$this->_id=$this->_user->id;
$this->setState('name', $this->_user->name);
$this->errorCode=self::ERROR_NONE;
}
}
Note that your authenticate function might be finding the user by a different attribute, you mostly want to change it to call logInUser when it has successfully authenticated the user.
Now create a static function called Impersonate that looks like this:
public static function impersonate($userId)
{
$ui = null;
$user = User::model()->findByPk($userId);
if($user)
{
$ui = new UserIdentity($user->email, "");
$ui->logInUser($user);
}
return $ui;
}
This function creates a UserIdentity for the specified userId and returns it. It uses our refactored logInUser function to log the user in. The advantage of using this function is that it avoids some of the private/protected access problems of using a static function. (There are some comments about this below that were added before this article was updated to include this refactor.)
Step 2: Create an impersonate action on your site controller:
public function actionImpersonate($id)
{
$ui = UserIdentity::impersonate($id);
if($ui)
Yii::app()->user->login($ui, 0);
$this->redirect(Yii::app()->homeUrl);
}
You can see that we're logging in as the impersonated user by the same method that the standard LoginForm uses. We'll then redirect to the home page of the site as the new user.
Step 3:
Protect your site/impersonate action. Obviously this action is very powerful. Be sure to add it to your restricted access control rules so that only properly authenticated administrators can access it.
Note that you'll have to log out and back in as a site administrator to become a different user.
using this when not in context
that static function will throw an error:
Using $this when not in object context in ...
a possible fix
I got it to work with this code:
public function impersonate($userId) { $identity = null; $user = Users::model()->findByPk($userId); if($user) { $identity = new UserIdentity($user->email, ""); $this->setUser($user); $this->errorCode = self::ERROR_NONE; } return $identity; }
updated
I've updated the article to remove the $this references. It really should be static.
protected
your static version will only work if your _user and _id are public, mine are protected so I have to make a new instance.
Updated
I've updated with a refactor of the code that logs in the user. This is what I'm actually doing in my application.
User information still exists as guest
When I try to use this, I get what looks to be a correct user identity, but when I try to login the user, it still looks like it is a guest:
UserIdentity Object ( [_id:UserIdentity:private] => 3 [_user:UserIdentity:private] => UserAccount Object ( [_new:CActiveRecord:private] => [_attributes:CActiveRecord:private] => Array ( [id] => 3 [email] => realuser@domain.com [password] => $hashedpasswordisgood [firstName] => Real [lastName] => User ) [_c:CActiveRecord:private] => [_pk:CActiveRecord:private] => 3 [_alias:CActiveRecord:private] => t [_errors:CModel:private] => Array ( ) [_validators:CModel:private] => [_scenario:CModel:private] => update [_e:CComponent:private] => [_m:CComponent:private] => ) [username] => realuser@domain.com [password] => [errorCode] => 0 [errorMessage] => [_state:CBaseUserIdentity:private] => Array ( [email] => realuser@domain.com [firstName] => Real [lastName] => User ) [_e:CComponent:private] => [_m:CComponent:private] => )
CWebUser Object ( [allowAutoLogin] => 1 [guestName] => Guest [loginUrl] => Array ( [0] => /site/login ) [identityCookie] => [authTimeout] => 36000 [absoluteAuthTimeout] => [autoRenewCookie] => 1 [autoUpdateFlash] => 1 [loginRequiredAjaxResponse] => [_keyPrefix:CWebUser:private] => c257a47be47a535222f61d0d689bce9e [_access:CWebUser:private] => Array ( ) [behaviors] => Array ( ) [_initialized:CApplicationComponent:private] => 1 [_e:CComponent:private] => [_m:CComponent:private] => )
If you have any questions, please ask in the forum instead.
Signup or Login in order to comment.